基于具有不同值的数字列合并两个Panda DataFrames,保留每个数据框的唯一变量



我试图合并两个需要匹配id的DataFrame,保留每个DataFrame的分类变量,并保留每个id/类别的总和。很抱歉,如果措辞有点不清楚,本质上我从两个数据帧开始,每个数据帧都为一些ID分配一个类别:

>>> print(df_a)
id   cat_a  sum_a
0  A    blue    800
1  B    blue    500
2  B   green    500
3  C  yellow    550
4  D     red   1000
>>> print(df_b)
id     cat_b  sum_b
0  A    square    700
1  A  triangle    100
2  B    circle    700
3  B  triangle    300
4  C  pentagon    550
5  D      line    800
6  D  triangle    200

从id=B来看,在cat_a中500/1000是蓝色,500/1000是绿色,在cat_B中700/1000是圆形,300/1000是三角形。

对于每个ID:,两个数据帧具有相同的总计

>>>print(df_a.groupby('id')['sum_a'].sum() == df_b.groupby('id')['sum_b'].sum())
id
A    True
B    True
C    True
D    True

我想创建一个新的DataFrame,df_c,它组合类别并在sum_c中分配和,这样原始和仍然与它们的原始DataFrame一致。这里有一个手工制作的例子:

>>> print(df_c)
id   cat_a     cat_b  sum_c
0  A    blue    square    700
1  A    blue  triangle    100
2  B    blue    circle    500
3  B   green    circle    200
4  B   green  triangle    300
5  C  yellow  pentagon    550
6  D     red      line    800
7  D     red  triangle    200

我可以通过对df_c的组成数据帧执行groupby,并检查它是否与原始数据帧匹配来确认df_c是正确的:

>>> df_c2a = df_c.groupby(['id', 'cat_a'], as_index=False)['sum_c'].sum()
>>> print(np.all(df_a.values == df_c2a.values))
True
>>> df_c2b = df_c.groupby(['id', 'cat_b'], as_index=False)['sum_c'].sum()
>>> print(np.all(df_b.values == df_c2b.values))
True

目前,我对如何创建前两个数据帧中的第三个数据帧df_c感到困惑。关于实现这一目标的最佳方式,有什么建议吗?


我试过对"id"进行左合并,但我似乎无法获得与匹配的总和

>>> df_c = df_a.merge(df_b, how='left', on='id')
>>> df_c['sum_c'] = df_c['sum_b']
>>> df_c = df_c.drop(['sum_a', 'sum_b'], axis=1)
>>> df_a_group = df_c.groupby(['id', 'cat_a'], as_index=False)['sum_c'].sum().reset_index(drop=True)
>>> print(df_a)
id   cat_a  sum_a
0  A    blue    800
1  B    blue    500
2  B   green    500
3  C  yellow    550
4  D     red   1000
>>> print(df_a_group)
id   cat_a  sum_c
0  A    blue    800
1  B    blue   1000
2  B   green   1000
3  C  yellow    550
4  D     red   1000

您可以合并两个数据帧:

df_c = df_a.merge(df_b, on = 'id', how = 'outer')
df_c['sum_c'] = df_c.apply(lambda x: x['sum_b']/2 if x['id'] == 'B' else x['sum_b'], axis = 1)

如果你的数据看起来不一样,你只需要计算如何分配总和。在你的例子中,它只需要id B.

最新更新