关于python:根据pandas dataframe中的键列减去列

Subtracting columns based on key column in pandas dataframe

我有两个数据帧看起来像

DF1:

1
2
3
4
5
   ID    A   B   C   D
0 'ID1' 0.5 2.1 3.5 6.6
1 'ID2' 1.2 5.5 4.3 2.2
2 'ID1' 0.7 1.2 5.6 6.0
3 'ID3' 1.1 7.2 10. 3.2

DF2:

1
2
3
4
5
   ID    A   B   C   D
0 'ID1' 1.0 2.0 3.3 4.4
1 'ID2' 1.5 5.0 4.0 2.2
2 'ID3' 0.6 1.2 5.9 6.2
3 'ID4' 1.1 7.2 8.5 3.0

df1可以有多个具有相同ID的条目,而每个ID只在df2中出现一次。同样,并非所有DF2中的ID都必须存在于DF1中。我不能用set_index()来解决这个问题,因为df1中的多行可以有相同的ID,而df1和df2中的ID没有对齐。

我想创建一个新的数据帧,在这里我根据匹配的ID从df1[['A','B','C','D']]中减去df2[['A','B','C','D']]中的值。

生成的数据帧如下所示:

df_新:

1
2
3
4
5
   ID     A    B   C   D
0 'ID1' -0.5  0.1 0.2 2.2
1 'ID2' -0.3  0.5 0.3 0.0
2 'ID1' -0.3 -0.8 2.3 1.6
3 'ID3'  0.5  6.0 1.5 0.2

我知道如何使用循环来实现这一点,但是由于我处理的是大量的数据,这一点都不实际。与大熊猫相处的最好方式是什么?


你只需要设置索引和减法

1
2
3
4
5
6
7
8
(df1.set_index('ID')-df2.set_index('ID')).dropna(axis=0)
Out[174]:
         A    B    C    D
ID                      
'ID1' -0.5  0.1  0.2  2.2
'ID1' -0.3 -0.8  2.3  1.6
'ID2' -0.3  0.5  0.3  0.0
'ID3'  0.5  6.0  4.1 -3.0

如果订单很重要,则为df2添加reindex

1
2
3
4
5
6
7
(df1.set_index('ID')-df2.set_index('ID').reindex(df1.ID)).dropna(axis=0).reset_index()
Out[211]:
      ID    A    B    C    D
0  'ID1' -0.5  0.1  0.2  2.2
1  'ID2' -0.3  0.5  0.3  0.0
2  'ID1' -0.3 -0.8  2.3  1.6
3  'ID3'  0.5  6.0  4.1 -3.0


与文(打败我)的提议类似,你可以使用pd.DataFrame.subtract

1
2
3
4
5
6
7
8
df1.set_index('ID').subtract(df2.set_index('ID')).reset_index()

         A    B    C    D
ID                      
'ID1' -0.5  0.1  0.2  2.2
'ID1' -0.3 -0.8  2.3  1.6
'ID2' -0.3  0.5  0.3  0.0
'ID3'  0.5  6.0  4.1 -3.0


一种方法是使用numpy。我们可以使用numpy.searchsorteddf2中提取所需的有序指数。

然后将其输入新数据帧的构造中。

1
2
3
4
5
6
7
8
9
10
11
12
idx = np.searchsorted(df2['ID'], df1['ID'])

res = pd.DataFrame(df1.iloc[:, 1:].values - df2.iloc[:, 1:].values[idx],
                   index=df1['ID']).reset_index()

print(res)

      ID    0    1    2    3
0  'ID1' -0.5  0.1  0.2  2.2
1  'ID2' -0.3  0.5  0.3  0.0
2  'ID1' -0.3 -0.8  2.3  1.6
3  'ID3'  0.5  6.0  4.1 -3.0