在Pandas中创建类似Excel的SUMIFS

Jul*_*man 5 python pandas

我最近了解pandas并很高兴看到它的分析功能.我正在尝试将Excel数组函数转换为Pandas,相当于我为创建性能归因报告而创建的自动化电子表格.在此示例中,我根据其他列中的条件在Excel中创建了一个新列:

={SUMIFS($F$10:$F$4518,$A$10:$A$4518,$C$4,$B$10:$B$4518,0,$C$10:$C$4518," ",$D$10:$D$4518,$D10,$E$10:$E$4518,$E10)}
Run Code Online (Sandbox Code Playgroud)

该公式基于某些条件对"F"数组​​(安全权重)中的值进行求和."A"数组(组合ID)是一定数字,"B"数组(安全ID)为零,"C"数组(组描述)是"","D"数组(开始日期)是行的日期我在,"E"数组(结束日期)是我所在行的日期.

在Pandas中,我正在使用DataFrame.使用前三个条件在数据框架上创建新列是直截了当的,但我在最后两个条件下遇到困难.

reportAggregateDF['PORT_WEIGHT'] = reportAggregateDF['SEC_WEIGHT_RATE']
          [(reportAggregateDF['PORT_ID'] == portID) &
           (reportAggregateDF['SEC_ID'] == 0) &
           (reportAggregateDF['GROUP_LIST'] == " ") & 
           (reportAggregateDF['START_DATE'] == reportAggregateDF['START_DATE'].ix[:]) & 
           (reportAggregateDF['END_DATE'] == reportAggregateDF['END_DATE'].ix[:])].sum()
Run Code Online (Sandbox Code Playgroud)

显然,最后两个条件中的.ix [:]对我来说没有做任何事情,但是有没有办法让这个总和以我所在的行为条件而没有循环?我的目标是不做任何循环,而是使用纯粹的向量操作.

guy*_*yrt 9

你想使用apply函数和lambda:

>> df
     A    B    C    D     E
0  mitfx  0  200  300  0.25
1     gs  1  150  320  0.35
2    duk  1    5    2  0.45
3    bmo  1  145   65  0.65
Run Code Online (Sandbox Code Playgroud)

假设我想将列C乘以E,但仅当列B == 1且D大于5时:

df['matches'] = df.apply(lambda x: x['C'] * x['E'] if x['B'] == 1 and x['D'] > 5 else 0, axis=1)
df.matches.sum()
Run Code Online (Sandbox Code Playgroud)

将其分为两个步骤可能更清晰:

df_subset = df[(df.B == 1) & (df.D > 5)]
df_subset.apply(lambda x: x.C * x.E, axis=1).sum()
Run Code Online (Sandbox Code Playgroud)

或者简单地使用乘法速度:

df_subset = df[(df.B == 1) & (df.D > 5)]
print sum(df_subset.C * df_subset.E)
Run Code Online (Sandbox Code Playgroud)

你想要在没有循环的情况下解决这个问题是绝对正确的.


Jul*_*man 1

我确信有更好的方法,但是这是循环完成的:

for idx, eachRecord in reportAggregateDF.T.iteritems():
reportAggregateDF['PORT_WEIGHT'].ix[idx] = reportAggregateDF['SEC_WEIGHT_RATE'][(reportAggregateDF['PORT_ID'] == portID) &            
    (reportAggregateDF['SEC_ID'] == 0) &            
    (reportAggregateDF['GROUP_LIST'] == " ") &             
    (reportAggregateDF['START_DATE'] == reportAggregateDF['START_DATE'].ix[idx]) &             
    (reportAggregateDF['END_DATE'] == reportAggregateDF['END_DATE'].ix[idx])].sum()
Run Code Online (Sandbox Code Playgroud)