Easy Way
Я думаю, что это сделает работу.Проблема с вашей потребностью в том, что ее нелегко поддерживать.Какой будет порядок столбцов «E», если однажды вам понадобится новый столбец?
df['shortage'] = df.A1 + df.B1 + df.C1 + df.D1
df['remaining'] = df['shortage'] - df.D - df.C - df.B - df.A
df.loc[df.remaining < 0, 'remaining'] = 0
df.C = df.C - df['shortage']
df.loc[df.C < 0, 'C'] = 0
df.B = df.C + df.B - df['shortage']
df.loc[df.B < 0, 'B'] = 0
df.A = df.C + df.B + df.A - df['shortage']
df.loc[df.A < 0, 'A'] = 0
df.D = df.C + df.B + df.A + df.D - df['shortage']
df.loc[df.D < 0, 'D'] = 0
for col in ['A1', 'B1', 'C1', 'D1']:
df.loc[df[col] != 0, col] = df.loc[df[col] != 0, 'remaining']
df = df.drop('shortage', axis=1)
Динамический путь
Поскольку приведенный выше код не является динамическим, я дам вам второй способниже, который позволяет вам иметь новые столбцы (например, столбец «E»). Единственное, что вам нужно сохранить, это строка заказа 1
order = ['C', 'B', 'A', 'D']
# get the list of shortage_col (those which starts with 1) and non_shortage_col (the others)
shortage_col = [col for col in df.columns.tolist() if col.endswith('1')]
non_shortage_col = [col for col in df.columns.tolist() if not (col.endswith('1') | (col == 'Item'))]
# add together all columns that are in shortage_col
df['shortage'] = np.sum(df[shortage_col].values.tolist(),axis=1)
df['remaining'] = df['shortage'] - np.sum(df[non_shortage_col].values.tolist(),axis=1)
df.loc[df.remaining < 0, 'remaining'] = 0
# loop through order to get the list of all previous values for each item in order
# returns a list like that [['C'], ['C', 'B'], ['C', 'B', 'A'], ['C', 'B', 'A', 'D']]
to_add = []
for i in range(len(order)):
list_of_previous = []
for index, element in enumerate(order):
if index < i + 1:
list_of_previous.append(element)
to_add.append(list_of_previous)
for i in range(len(order)):
col = order[i]
# same as : df.D = df.C + df.B + df.A + df.D - df['shortage']
df[col] = np.sum(df[to_add[i]].values.tolist(),axis=1) - df['shortage']
# same as : df.loc[df.D < 0, 'D'] = 0
df.loc[df[col] < 0, col] = 0
for col in ['A1', 'B1', 'C1', 'D1']:
df.loc[df[col] != 0, col] = df.loc[df[col] != 0, 'remaining']
df = df.drop('shortage', axis=1)