我读了很多关于merge()
and join()
的方法pandas.DataFrames
,并在我自己的问题上尝试这些,但没有完全找到解决方案。
我有一个非常大的数据文件 (.csv),其中包含各种 ID 每小时的消耗量。我想汇总每个 ID 每月的消耗量。
由于内存限制,我需要处理每小时消耗文件read_csv
分块(使用chunk_size
选项),并且最终会在几个月内消耗大量 ID 消耗的 DataFrame,例如:
df1 =
Month Dec Nov
ID
XXX 4.0 1.0
YYY 8.0 3.0
ZZZ 4.0 1.0
df2 =
Month Dec Nov Oct
ID
AAA 1.0 7.0 9.0
BBB 0.0 NaN 2.0
YYY 5.0 5.0 0.0
为这篇文章生成:
df1 = pd.DataFrame({'ID': ['XXX','XXX','YYY','YYY','ZZZ','ZZZ'],
'Month': ['Nov','Dec']*3,
'Consumption': [1.0,4.0,3.0,8.0,1.0,4.0]})
df1 = df1.pivot(index='ID', columns='Month', values='Consumption')
df2 = pd.DataFrame({'ID': ['AAA','AAA','AAA','YYY','YYY','YYY','BBB','BBB','BBB'],
'Month': ['Oct','Nov','Dec']*3,
'Consumption': [9,7,1,0,5,5,2,np.nan,0]})
df2 = df2.pivot(index='ID', columns='Month', values='Consumption')
请注意,消耗量之间存在差异0.0
and NaN
. 0.0
意味着至少有一个消耗读数0.0
月内,但是NaN
表示根本没有记录消耗值,在这种情况下,不能假设为 0。出于我的目的,这种差异必须保持明显。
由于数据文件是以块的形式处理的,因此有些 ID 会出现在多个 DataFrame 中,例如YYY
,并且,对于这些 ID,有时月份也会重叠,例如Nov
for ID YYY
。在此情况下,上半月的消费量为df1
下半场是在df2
.
因此,为了聚合消耗,我需要按“ID”合并这些 DataFrame,并对重叠的“月份”中的值求和。
直接求和DataFrames 产生许多 NaN:
df1 + df2 =
Month Dec Nov Oct
ID
AAA NaN NaN NaN
BBB NaN NaN NaN
XXX NaN NaN NaN
YYY 13.0 8.0 NaN
ZZZ NaN NaN NaN
我认为这是因为在汇总 ID/月数时df1
没有出现的df2
它返回一个 NaN。
外合并生成重叠月份的后缀列:
df1.merge(df2,how='outer',on='ID') =
Month Dec_x Nov_x Dec_y Nov_y Oct
ID
XXX 4.0 1.0 NaN NaN NaN
YYY 8.0 3.0 5.0 5.0 0.0
ZZZ 4.0 1.0 NaN NaN NaN
AAA NaN NaN 1.0 7.0 9.0
BBB NaN NaN 0.0 NaN 2.0
我无法得到combine_first
做我想做的事。
我想要的是中间的东西,看起来像这样:
Month Dec Nov Oct
ID
XXX 4.0 1.0 NaN
YYY 13.0 8.0 0.0
ZZZ 4.0 1.0 NaN
AAA 1.0 7.0 9.0
BBB 0.0 NaN 2.0
重叠月份的总和使得x + NaN = x
, NaN + y = y
and NaN + NaN = NaN
.
我看到的一种解决方案是进行合并,然后对重叠的列求和,忽略 NaN:
df3 = df1.merge(df2,how='outer',on='ID',suffixes=['','_x'])
overlapping_months_sufx = df3.columns.values[df3.columns.str.endswith('_x')]
for mnth_sufx in overlapping_months_sufx:
mnth = mnth_sufx[:-2]
df3[mnth][df3[mnth_sufx].notnull()] = df3[mnth].fillna(0) + df3[mnth_sufx]
df3=df3.drop(columns=mnth_sufx)
df3 =
Month Dec Nov Oct
ID
XXX 4.0 1.0 NaN
YYY 13.0 8.0 0.0
ZZZ 4.0 1.0 NaN
AAA 1.0 7.0 9.0
BBB 0.0 NaN 2.0
考虑到该数据集的大小,如果能有最有效的方法来聚合所有这些数据,那就太好了。有没有更好的方法来做到这一点,也许一步到位?
谢谢,
克里斯