我正在寻找一种更有效,更可维护的方式来按组有条件地补偿值。最容易显示示例。
Offset == False
的值始终为负,Offset == True
的值始终为负。我想做的是通过Label将负值“折叠”为正值(从0开始)。
注意Label
+ Offset
的组合始终是唯一的。由于Offset
是布尔值,因此每个标签最多只能有2行。
示例1
df = pd.DataFrame({'Label': ['L1', 'L2', 'L3', 'L3'],
'Offset': [False, False, False, True],
'Value': [100, 100, 50, -100]})
# input
# Label Offset Value
# 0 L1 False 100
# 1 L2 False 100
# 2 L3 False 50
# 3 L3 True -100
所需的输出:
Label Offset Value
0 L1 False 100
1 L2 False 100
2 L3 False 0
3 L3 True -50
示例2
df = pd.DataFrame({'Label': ['L1', 'L2', 'L3', 'L3'],
'Offset': [False, False, False, True],
'Value': [100, 100, 100, -50]})
# input
# Label Offset Value
# 0 L1 False 100
# 1 L2 False 100
# 2 L3 False 100
# 3 L3 True -50
所需的输出:
Label Offset Value
0 L1 False 100
1 L2 False 100
2 L3 False 50
3 L3 True 0
当前效率低下的解决方案
我当前的解决方案是手动循环,速度慢且难以维护:
for label in df['Label'].unique():
mask = df['Label'] == label
if len(df.loc[mask]) == 2:
val_false = df.loc[~df['Offset'] & mask, 'Value'].iloc[0]
val_true = df.loc[df['Offset'] & mask, 'Value'].iloc[0]
if val_false > abs(val_true):
df.loc[~df['Offset'] & mask, 'Value'] += val_true
df.loc[df['Offset'] & mask, 'Value'] = 0
else:
df.loc[~df['Offset'] & mask, 'Value'] = 0
df.loc[df['Offset'] & mask, 'Value'] += val_false
我正在寻找一种矢量化或至少部分矢量化的解决方案,以提高性能并摆脱这种混乱局面。
答案 0 :(得分:6)
也许:
label_sums = df.Value.groupby(df.Label).transform(sum)
df["new_sum"] = label_sums.where(np.sign(label_sums) == np.sign(df.Value), 0)
这给了我
In [42]: df
Out[42]:
Label Offset Value new_sum
0 L1 False 100 100
1 L2 False 100 100
2 L3 False 50 0
3 L3 True -100 -50
4 L4 False 100 100
5 L5 False 100 100
6 L6 False 100 50
7 L6 True -50 0
答案 1 :(得分:4)
这是我所拥有的最好的方法:创建一个辅助列以查找显示聚合的位置,然后将该组的其他成员设置为0
df['aux'] = abs(df['Value'])
idx = abs(df.groupby(['Label'])['aux'].transform(max)) == abs(df['aux'])
df['aux2'] = False
df.loc[idx,'aux2'] = True
df = df.join(df.groupby('Label').Value.sum(), on='Label', rsuffix = 'jpp')
df.loc[df['aux2']==False, 'Valuejpp'] = 0
df = df.drop(['aux', 'aux2','Value'], axis = 1)
结果
Label Offset Valuejpp
0 L1 False 100
1 L2 False 100
2 L3 False 0
3 L3 True -50
答案 2 :(得分:4)
DSM中的数据
df1=df.copy()
df.loc[df.Offset,'Value']=df.Value.abs()
s1=(df.groupby('Label').Value.diff().lt(0)).groupby(df['Label']).transform('any')
s2=df.groupby('Label').Value.transform('count')
s3=df1.groupby('Label').Value.transform('sum')
np.where(s2<=1,df1.Value,np.where(s1,s3*(-df1.Offset),s3*df1.Offset))
Out[757]: array([100, 100, 0, -50, 100, 100, 50, 0], dtype=int64)