【问题标题】:Subtract two Pandas DataFrames joined on multiple column values减去在多个列值上连接的两个 Pandas DataFrame
【发布时间】:2019-06-29 15:26:38
【问题描述】:

我试图从 DataFrame B 中一列的值中减去 DataFrame A 中一列的值,但前提是多个列值彼此相等。

假设(虚构):

DataFrame A:
Index    Department  Speciality   TargetMonth Capacity
1        Sales       Cars         2019-1      150
2        Sales       Cars         2019-2      120
3        Sales       Furniture    2019-1      110
4        IT          Servers      2019-1      100

DataFrame B:
Index    Department  Speciality   TargetMonth Required
1        Sales       Cars         2019-1      100
2        Sales       Cars         2019-2      120
3        IT          Servers      2019-1      50
4        Sales       Furniture    2019-1      50

与 A 相比,我故意将 DataFrame B 中索引 3 和 4 的顺序交换了。我的目标是从 DataFrame A 的容量列中减去 DataFrame B 它的Required 列作为所需的容量小时,并产生另一个不一定需要排序的列表:

Index    Department  Speciality   TargetMonth Result
1        Sales       Cars         2019-1      50
2        Sales       Cars         2019-2      0
3        Sales       Furniture    2019-1      60
4        IT          Servers      2019-1      50

因此,从技术上讲,仅减去,并且仅当所有列值相互匹配且不基于顺序时,因为某些行可能在一个列表或另一个列表中丢失。

我可以用一些 for 循环和条件来解决这个问题,但我想有一个干净整洁的 Pandas 方法可以用 .subtract 解决这个问题,尽管它是我目前卡在的“加入”部分。

提前感谢您的宝贵时间。

【问题讨论】:

    标签: python python-3.x pandas


    【解决方案1】:

    我会用键合并:

    对于此解决方案,将您的数据框 A 作为 dfA 并将数据框作为 dfB

       df_result =  pd.merge(dfA, dfB, how='inner', on=['Department','Speciality','TargetMonth'])
    

    这将根据键将数据框放在一起:['Department','Speciality','TargetMonth'] 并将生成一个数据框,其中键出现在两个数据框中(how = 'inner')。

    I.E.如果 dfB 中有一个键是:

       {'Department': 'IT','Speciality':'Furniture','TargetMonth':2019-1}
    

    该值不会出现在数据框 df_result 中。更多信息可以在这里找到 - https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html

    然后使用 Pandas 向量化的解决方案:

       df_result['Result'] = df_result['Capacity'] - df_result['Required']
    

    【讨论】:

    • 不过,稍后我也确实使用了您的合并建议来规范化并将我的结果连接回汇总 DataFrame。也感谢您的建议!
    【解决方案2】:

    这就是Index 如此有用的原因,减法将在索引(行和列)上对齐。

    dfA = dfA.set_index(['Department', 'Speciality', 'TargetMonth'])
    dfB = dfB.set_index(['Department', 'Speciality', 'TargetMonth'])
    
    dfA.sub(dfB.rename(columns={'Required': 'Capacity'}), fill_value=0)
    
                                       Capacity
    Department Speciality TargetMonth          
    IT         Servers    2019-1             50
    Sales      Cars       2019-1             50
                          2019-2              0
               Furniture  2019-1             60
    

    【讨论】:

    • 我选择了这个答案,因为这正是我所需要的,并且使用 reset_index() 我能够得到扁平的结果。好东西!
    • 是的,这 3 个级别似乎是每个表的唯一键,所以这非常有用。重复索引会使事情变得奇怪,因为减法会导致重复键的外积。在这些情况下,在减法之前进行聚合可能会很有用。
    猜你喜欢
    • 2021-07-22
    • 1970-01-01
    • 2023-02-01
    • 2015-06-14
    • 2021-06-20
    • 2016-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多