合并熊猫 groupBy 对象
Posted
技术标签:
【中文标题】合并熊猫 groupBy 对象【英文标题】:Merge pandas groupBy objects 【发布时间】:2019-02-24 18:40:01 【问题描述】:我有一个包含 2.92 亿行 (6GB) 的 CSV 格式的庞大数据集。 Panda 的read_csv
功能不适用于这么大的文件。所以我正在使用这段代码迭代地读取小块(1000万行)的数据:
for chunk in pd.read_csv('hugeData.csv', chunksize=10**7):
#something ...
在#something 中,我根据某些列对行进行分组。所以在每次迭代中,我都会得到新的 groupBy 对象。我无法合并这些 groupBy 对象。
一个更小的虚拟示例如下:
这里的dummy.csv
是一个28 行的CSV 文件,是一些国家在某年的贸易报告。 sitc 是一些产品代码,export 是大约十亿美元的出口金额。 (请注意,数据是虚构的)
year,origin,dest,sitc,export
2000,ind,chn,2146,2
2000,ind,chn,4132,7
2001,ind,chn,2146,3
2001,ind,chn,4132,10
2002,ind,chn,2227,7
2002,ind,chn,4132,7
2000,ind,aus,7777,19
2001,ind,aus,2146,30
2001,ind,aus,4132,12
2002,ind,aus,4133,30
2000,aus,ind,4132,6
2001,aus,ind,2146,8
2001,chn,aus,1777,9
2001,chn,aus,1977,31
2001,chn,aus,1754,12
2002,chn,aus,8987,7
2001,chn,aus,4879,3
2002,aus,chn,3489,7
2002,chn,aus,2092,30
2002,chn,aus,4133,13
2002,aus,ind,0193,6
2002,aus,ind,0289,8
2003,chn,aus,0839,9
2003,chn,aus,9867,31
2003,aus,chn,3442,3
2004,aus,chn,3344,17
2005,aus,chn,3489,11
2001,aus,ind,0893,17
我将其拆分为两个 14 行的数据,并根据年份、原点、目的地对它们进行分组。
for chunk in pd.read_csv('dummy.csv', chunksize=14):
xd = chunk.groupby(['origin','dest','year'])['export'].sum();
print(xd)
结果:
origin dest year
aus ind 2000 6
2001 8
chn aus 2001 40
ind aus 2000 19
2001 42
2002 30
chn 2000 9
2001 13
2002 14
Name: export, dtype: int64
origin dest year
aus chn 2002 7
2003 3
2004 17
2005 11
ind 2001 17
2002 14
chn aus 2001 15
2002 50
2003 40
Name: export, dtype: int64
如何合并两个 GroupBy 对象?
合并它们是否会再次在大数据中产生内存问题?通过查看数据性质的预测,如果合并得当,行数肯定会减少至少 10-15 倍。
基本目标是:
给定原产国和目的地国, 我需要每年绘制它们之间的总出口量。 每次对整个数据进行查询都需要花费大量时间。
xd = chunk.loc[(chunk.origin == country1) & (chunk.dest == country2)]
因此,我想通过按 groupBy 的方式排列它们来节省时间。
非常感谢任何建议。
【问题讨论】:
对于 origin : aus 和 dest : ind,合并数据应该是 : 2000 : 6, 2001 : 25, 2002 : 14 两个 groupby 对象只是数据帧切片,您可以使用标准工具将它们合并,例如pd.concat
、pd.merge
、pd.join
。
我在 xd0 中存储了第一个拆分,在 xd1 中存储了第二个拆分并应用了pd.merge(xd0,xd1,on="origin")
。我收到错误:ValueError: can not merge DataFrame with instance of type <class 'pandas.core.series.Series'>
这是有效的:pd.concat([xd0,xd1], axis=1)
。但它创建了两个不同的导出列。 [澳大利亚工业 2000 6.0 NaN],[澳大利亚工业 2001 8.0 17.0],[澳大利亚工业 2002 NaN 14.0]
你能显示你需要的输出吗?
【参考方案1】:
您可以使用pd.concat
加入groupby结果,然后申请sum
:
>>> pd.concat([xd0,xd1],axis=1)
export export
origin dest year
aus ind 2000 6 6
2001 8 8
chn aus 2001 40 40
ind aus 2000 19 19
2001 42 42
2002 30 30
chn 2000 9 9
2001 13 13
2002 14 14
>>> pd.concat([xd0,xd1],axis=1).sum(axis=1)
origin dest year
aus ind 2000 12
2001 16
chn aus 2001 80
ind aus 2000 38
2001 84
2002 60
chn 2000 18
2001 26
2002 28
【讨论】:
@hellpanderr 先生,问题解决了。合并和创建一个大的简化字典(1,000,816 行)需要 9 分钟。进一步的查询执行花费的时间(以毫秒为单位)可以忽略不计。有什么方法可以将 groupBy 对象以字典形式保存在本地硬盘中。这样下次重新开始时,我可以直接加载数据(显然不到 9 分钟)并输出查询。 你想保存pd.concat
的结果吗?一个巨大的系列?
是的,先生。完整的巨大系列。行数是100万,所以我希望它可以保存在一些MB中,它们的加载时间会非常少。所以从下一次开始,如果只是 load('series.xyz') 我会在几秒钟内得到系列数据。
@hellpanderr 先生,保存为我打算将其写入我的硬盘,就像我们在 xd.to_csv('series.csv')
中所做的一样。
先生,我想通了。 xd.to_pickle("./backup.pkl")
然后回电xdBack = pd.read_pickle("./dummy.pkl")
。非常感谢您的帮助。以上是关于合并熊猫 groupBy 对象的主要内容,如果未能解决你的问题,请参考以下文章