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)iteratorchunksize=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 位。)这就是 iteratorchunksize 解决问题的方法:允许您在需要时进行权衡。

【讨论】:

慢于什么?在 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 中清理数据

如何从带有额外分隔符的 csv 在 python 中创建 pandas 数据框?

Python数据分析pands中的Merge与join

利用Python数据分析-Numpy和Pands篇

Python pands和matplotlib常用命令

如何使用带有新行的python将列表保存为.csv文件?