python - 使用带有大 csv 的 pandas 结构(迭代和块大小)
Posted
技术标签:
【中文标题】python - 使用带有大 csv 的 pandas 结构(迭代和块大小)【英文标题】:python - Using pandas structures with large csv(iterate and chunksize) 【发布时间】:2016-02-12 02:17:38 【问题描述】:我有一个大的 csv 文件,大约 600mb 有 1100 万行,我想创建统计数据,如数据透视图、直方图、图表等。显然只是想正常读取它:
df = pd.read_csv('Check400_900.csv', sep='\t')
不起作用,所以我在类似的帖子中发现了 iterate 和 chunksize,所以我使用了
df = pd.read_csv('Check1_900.csv', sep='\t', iterator=True, chunksize=1000)
一切都好,例如,我可以 print df.get_chunk(5)
搜索整个文件
for chunk in df:
print chunk
我的问题是我不知道如何将下面这些东西用于整个 df 而不仅仅是一个块
plt.plot()
print df.head()
print df.describe()
print df.dtypes
customer_group3 = df.groupby('UserID')
y3 = customer_group.size()
我希望我的问题没有那么令人困惑
【问题讨论】:
您还没有提出问题。你有什么问题? @saladi 我的问题是如何使用 df 而不必一次将其全部加载到内存中。 我认为你提到的问题是这个***.com/questions/29334463/… 【参考方案1】:这可能不会直接回答问题,但是当您必须加载大数据集时,这是一个很好的做法,在读取数据集时隐藏列的 dtypes。此外,如果您知道需要哪些列,请使用 usecols
参数仅加载这些列。
df = pd.read_csv("data.csv",
usecols=['A', 'B', 'C', 'Date'],
dtype='A':'uint32',
'B':'uint8',
'C':'uint8'
,
parse_dates=['Date'], # convert to datetime64
sep='\t'
)
【讨论】:
如果这不能回答问题,您可以将此信息添加为评论。 我必须至少有 50 个声望才能发表评论:/。我认为这个建议对任何处理“大”数据集的人来说都是有用的。 (我只能评论我自己的答案)【参考方案2】:解决方案,如果需要创建一个大的DataFrame
,如果需要一次处理所有数据(有什么可能,但不是recommended):
然后对所有块使用concat 到df,因为函数的输出类型:
df = pd.read_csv('Check1_900.csv', sep='\t', iterator=True, chunksize=1000)
不是数据框,而是pandas.io.parsers.TextFileReader
- source。
tp = pd.read_csv('Check1_900.csv', sep='\t', iterator=True, chunksize=1000)
print tp
#<pandas.io.parsers.TextFileReader object at 0x00000000150E0048>
df = pd.concat(tp, ignore_index=True)
我认为有必要将参数ignore index 添加到函数concat
,因为避免索引的重复。
编辑:
但是如果想要处理像聚合这样的大数据,最好使用dask
,因为它提供了先进的并行性。
【讨论】:
他可以通过tp.read()
获取数据帧,但它可能不适合他的记忆,所以他问您是否可以在不完全加载的情况下工作。
我试过了,但我又用完了内存,'MemoryError'
我的内存大小是6gb
我收到错误 NotImplementedError: 'nrows' 和 'chunksize' 还不能一起使用。我应该删除块大小吗?
这是一个糟糕的主意,这正是@hellpanderr 在第一条评论中建议的原因。这与只调用read_csv
而不使用chunksize
具有相同的效果,除了它需要两倍的内存(因为你现在不仅要保存巨大的DataFrame,而且还要保存所有加起来到那个DataFrame 的块同时)。这不可能解决 OP 的问题,只会让情况变得更糟。【参考方案3】:
你确实不需要在这里需要concat
。这就像写sum(map(list, grouper(tup, 1000)))
而不是list(tup)
。 iterator
和 chunksize=1000
所做的唯一事情就是为您提供一个读取器对象,该对象可以迭代 1000 行 DataFrame,而不是读取整个数据。如果您想要一次完成所有操作,请不要使用这些参数。
但是如果一次将整个文件读入内存太昂贵(例如,占用太多内存以至于你得到一个MemoryError
,或者通过把它扔进交换地狱来减慢你的系统爬行),这正是@ 987654327@是为了。
问题是您将生成的迭代器命名为df
,然后尝试将其用作DataFrame。它不是数据框;它是一个迭代器,可以一一提供 1000 行 DataFrame。
当你这样说时:
我的问题是我不知道如何在整个 df 中使用下面这些东西,而不是只在一个块中使用
答案是你不能。如果你不能将整个东西加载到一个巨大的 DataFrame 中,你就不能使用一个巨大的 DataFrame。你必须围绕块重写你的代码。
而不是这个:
df = pd.read_csv('Check1_900.csv', sep='\t', iterator=True, chunksize=1000)
print df.dtypes
customer_group3 = df.groupby('UserID')
……你必须这样做:
for df in pd.read_csv('Check1_900.csv', sep='\t', iterator=True, chunksize=1000):
print df.dtypes
customer_group3 = df.groupby('UserID')
通常,您需要做的是汇总一些数据 - 将每个数据块缩减为更小的数据,仅包含您需要的部分。例如,如果要按组对整个文件求和,可以groupby
每个块,然后按组对块求和,并为每个组存储一个系列/数组/列表/字典。
当然,这比一次汇总一个巨大的系列要复杂一些,但没有办法解决。 (除非购买更多 RAM 和/或切换到 64 位。)这就是 iterator
和 chunksize
解决问题的方法:允许您在需要时进行权衡。
【讨论】:
慢于什么?在 1000 行块上调用groupby
所花费的时间与在 1000 行整个文件 DataFrame 上调用 groupby
所花费的时间完全相同。在我的笔记本电脑上花费不到 1 毫秒。如果您必须这样做 1000 次,则几乎需要一秒钟。处理一个您根本无法处理的文件是不是太慢了?【参考方案4】:
您需要连接夹头。例如:
df2 = pd.concat([chunk for chunk in df])
然后在df2
上运行你的命令
【讨论】:
感谢您的回复,但我再次收到“MemoryError” 这只是 jezrael 答案的稍差版本。以上是关于python - 使用带有大 csv 的 pandas 结构(迭代和块大小)的主要内容,如果未能解决你的问题,请参考以下文章
使用大型(1.7gig)csv 文件在 python 中清理数据