2017-05-26 111 views
1

认为我有两个pandas DataFrame S作为如下,Python的大熊猫合并两个DataFrames具有条件逻辑

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中增加一个新列,名为TARGET。为了计算列TARGET内的值,

  1. 我得在df_actualACTUAL值一定IDNAMEPRODUCTCHANNEL,然后拿到TARGETdf_target为同一IDNAMEPRODUCT
  2. 然后使用每个CHANNEL的贡献与总CHANNEL某些IDNAMEPRODUCT计算每个CHANNELTARGET值。

例如,以获得新的TARGETID 1,NAME A,PRODUCT W,和CHANNEL G,I需要使用此公式289 *(233 /(233 + 4))。

  • 289来自TARGETdf_target
  • 233来自对CHANNELģ
  • df_actualACTUAL
  • 4来自于CHANNEL中号
  • df_actualACTUAL

我的真实数据是相当庞大,超过1个百万行。所以如果你能提出矢量化解决方案,我会非常感激。尽管如此,任何建议将不胜感激。谢谢。

回答

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 
+0

很好的解决方案;) – jezrael

+0

@jezrael,谢谢:) – MaxU

+0

谢谢!这正是我正在寻找的。整洁,优雅,快速!再一次,非常感谢你! – arnold