Панды - вычитание из столбцов через приоритет

Простая иллюстрация того, что я пытаюсь сделать: учитывая набор данных о заработной плате с regular столбцами over_time , double_time , lunch_break , я хочу вычесть столбец lunch_break из других столбцов времени в указанном порядке до минуты обеденного перерыва исчерпаны. Например, минуты lunch_break на lunch_break должны выходить из regular , затем over_time , затем double_time . Итак, дан следующий набор данных:

import pandas as pd

payroll = [
    {'regular': 120, 'over_time':  60, 'double_time':   0, 'lunch_break': 30},
    {'regular':  15, 'over_time':  60, 'double_time':  30, 'lunch_break': 45},
    {'regular':  15, 'over_time':  15, 'double_time': 120, 'lunch_break': 45},
    {'regular':   0, 'over_time': 120, 'double_time': 120, 'lunch_break': 30}
]

payroll_df = pd.DataFrame(payroll)

Мне нужен результат:

result = [
    {'regular': 90, 'over_time': 60, 'double_time':   0}, # 30 from reg
    {'regular':  0, 'over_time': 30, 'double_time':  30}, # 15 from reg, 30 from ovr
    {'regular':  0, 'over_time':  0, 'double_time': 105}, # 15 from reg, 15 from ovr, 15 from dbl
    {'regular':  0, 'over_time': 90, 'double_time': 120}, # 0 from reg, 30 from ovr
]

result_df = pd.DataFrame(result)

Есть ли хороший способ сделать это с помощью панд?

Всего 3 ответа


Один из способов сделать это

regular = np.where(payroll_df['regular']-payroll_df['lunch_break']>0, payroll_df['regular']-payroll_df['lunch_break'],0)
b=np.where(regular>0, payroll_df['over_time'],payroll_df['over_time']+(payroll_df['regular']-payroll_df['lunch_break']))
over_time = np.where(b>0,b,0)
double_time= np.where(b<0,payroll_df['double_time']+b,payroll_df['double_time'])
result_df  = pd.DataFrame({'regular': regular,'over_time': over_time,'double_time': double_time})
result_df

выход

   regular  over_time   double_time
0   90             60   0
1   0              30   30
2   0               0   105
3   0              90   120

Векторизованная версия

df = payroll_df.copy()
df['regular'] = df.regular - df['lunch_break']
df.loc[df.regular < 0, 'over_time'] +=  df[df.regular < 0].regular
df.loc[df.over_time < 0, 'double_time'] += df[df.over_time < 0].over_time
df[df < 0] = 0
print(df.drop(columns='lunch_break'))

   regular  over_time  double_time
0       90         60            0
1        0         30           30
2        0          0          105
3        0         90          120

def subtract_lunch(row):
    remaining = row['lunch_break']
    for col in time_priority:
        if row[col] >= remaining:
            row[col] = row[col] - remaining
            break
        remaining = remaining - row[col]
        row[col] = 0
    return row[time_priority]

time_priority = ['regular', 'over_time', 'double_time']

payroll_df.apply(subtract_lunch, axis = 1)

Вы не говорите, как хотите, чтобы случай, когда lunch_break больше, чем другие, вместе взятые, обрабатывается. Мой код просто устанавливает все остальные столбцы в ноль, но не указывает на превышение.


Есть идеи?

10000