Python Pandas使用条件逻辑合并两个DataFrame

时间:2017-05-26 11:44:05

标签: python pandas numpy

假设我有两个pandas DataFrame如下,

df_actual

ID  NAME    PRODUCT CHANNEL ACTUAL
1   A       W       G       233
1   A       W       M       4
1   A       X       G       188
1   A       X       M       4
1   A       Y       G       37
1   A       Y       M       4
1   A       Z       G       272
1   A       Z       M       4

df_target

ID  NAME    PRODUCT TARGET
1   A       W       289
1   A       X       253
1   A       Y       36
1   A       Z       334

我希望得到如下结果,

ID  NAME    PRODUCT CHANNEL ACTUAL  TARGET  
1   A       W       G       233     284     <<< 289 * (233/(233+4))
1   A       W       G       4       5       <<< 289 * (4/(233+4))
1   A       X       G       188     248     <<< 253 * (188/(248+5))
1   A       X       G       4       5       <<< 253 * (4/(248+5))
1   A       Y       M       37      32      …
1   A       Y       M       4       4       …
1   A       Z       M       272     329     …
1   A       Z       M       4       5       …

基本上我想要做的是,在名为df_actual的{​​{1}}中添加一个新列。为了计算列TARGET中的值,

  1. 对于某些TARGETACTUALdf_actualID,我必须在NAME中获取PRODUCT值,然后获取CHANNEL中的TARGET值与之前相同的df_targetIDNAME
  2. 然后使用每个PRODUCT对特定TARGETCHANNEL的总CHANNEL的贡献计算每个CHANNEL的新ID值}和NAME
  3. 例如,要获取PRODUCT 1,TARGET A,ID W和NAME G的新PRODUCT值,我需要使用这个公式289 *(233 /(233 + 4))。

    • 289来自CHANNEL中的TARGET值。
    • 233来自df_targetACTUAL的{​​{1}} df_actual
    • 4来自CHANNEL ACTUAL df_actual CHANNEL的值{{1}}

    我的真实数据非常庞大,超过1 Mio行。因此,如果您可以建议矢量化解决方案,我将非常感谢。尽管如此,我们将非常感谢任何建议。感谢。

1 个答案:

答案 0 :(得分:3)

考虑以下矢量化方法:

In [39]: m = df_actual.merge(df_target)

In [40]: m
Out[40]:
   ID NAME PRODUCT CHANNEL  ACTUAL  TARGET
0   1    A       W       G     233     289
1   1    A       W       M       4     289
2   1    A       X       G     188     253
3   1    A       X       M       4     253
4   1    A       Y       G      37      36
5   1    A       Y       M       4      36
6   1    A       Z       G     272     334
7   1    A       Z       M       4     334

In [41]: m['TARGET'] = (m.TARGET * m.ACTUAL / m.groupby(['NAME','PRODUCT'])['ACTUAL'].transform('sum')).round()

In [42]: m
Out[42]:
   ID NAME PRODUCT CHANNEL  ACTUAL  TARGET
0   1    A       W       G     233   284.0
1   1    A       W       M       4     5.0
2   1    A       X       G     188   248.0
3   1    A       X       M       4     5.0
4   1    A       Y       G      37    32.0
5   1    A       Y       M       4     4.0
6   1    A       Z       G     272   329.0
7   1    A       Z       M       4     5.0