合并熊猫 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.concatpd.mergepd.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 对象的主要内容,如果未能解决你的问题,请参考以下文章

如何在熊猫的 groupby 对象中获取组数?

groupby对象熊猫的绝对值的平均值

获取熊猫 groupby 对象中多列的最大聚合

熊猫:GroupBy .pipe() 与 .apply()

Python:用 groupby 绘制熊猫数据框 - 奇怪的输出

使用 pandas groupby 查找列的唯一组合并另存为 df