Я ищу более эффективный и поддерживаемый способ условного смещения значений по группам. Проще всего показать пример.
Значение всегда неотрицательно для Offset == False
и всегда отрицательно для Offset == True
. Что я собираюсь сделать, так это «свернуть» положительные значения (с полем 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
Я ищу векторизованное или хотя бы частично векторизованное решение для повышения производительности и избавления от этого беспорядка.