【问题标题】:Subtracting columns based on key column in pandas dataframe根据熊猫数据框中的键列减去列
【发布时间】:2018-10-13 22:49:43
【问题描述】:

我有两个看起来像的数据框

df1:

   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:

   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_new:

   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

我知道如何使用循环来执行此操作,但由于我要处理大量数据,这根本不实用。使用 Pandas 解决此问题的最佳方法是什么?

【问题讨论】:

    标签: python python-3.x pandas dataframe


    【解决方案1】:

    你只需要 set_index 和减法

    (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

    (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
    

    【讨论】:

    • 第二个解决方案正是我所需要的,因为顺序确实对过程后期使用结果数据帧很重要。
    • @AndersT 啊:-) 快乐编码
    【解决方案2】:

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

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

    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
    

    【讨论】:

    • 我可以理解为什么它被否决了。顺便说一句,这不是我。与更简单的解决方案相比,有些人可能认为它不是很pythonic。运行这个:import this.
    【解决方案3】:

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

    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
    

    【讨论】:

    • 请注意,您确实丢失了原始数据帧的顺序。这可能很重要,也可能不重要。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-10
    • 2020-07-06
    • 1970-01-01
    • 2020-12-30
    相关资源
    最近更新 更多