Возможный подход.Задача разбита на 2 части - получить фактическое количество материала (которое не может быть отрицательным) и проанализировать нагрузки (группы строк, когда есть какое-либо количество материала, которое нужно раздавить на текущем временном шаге).
import numpy as np
import pandas as pd
def get_load(df):
""" get loaded material minus crushed material """
current_load = (df['A'] - df['B']).values
if current_load[0] < 0:
current_load[0] = 0
for idx in range(1, len(current_load)):
correct_value = current_load[idx - 1] + current_load[idx]
if correct_value < 0:
current_load[idx] = 0
else:
current_load[idx] = correct_value
return current_load
def get_work_load_chunk_stat(df):
""" get chunks when material actually crushing """
if df['load'].sum() == 0:
return
ans = pd.DataFrame(
{'indexA': [df.iloc[0, :]['indexA']],
'total_load': [df['A'].sum()],
'loads_qty': [df[df['A'] > 0]['A'].count()],
'indexB': [df.iloc[-1, :]['indexB']],
'total_work': [df['B'].sum()]})
return ans
if __name__ == '__main__':
A = {'indexA': range(22),
'A': [0, 300, 0, 0, 0, 0, 400, 0, 100, 0, 0, 0, 300, 0, 0, 0, 0, 400, 0, 100, 0, 0]}
B = {'indexB': range(22),
'B': [99, 102, 103, 94, 120, 145, 114, 126, 117, 107, 87, 99, 102, 103, 94, 120, 145, 114, 126, 117, 107, 87]}
data = pd.concat([pd.DataFrame(data=A), pd.DataFrame(data=B)], axis=1)
data['load'] = get_load(data)
data['load_check'] = np.where(data['load'] == 0, 1, 0)
data['load_check'] = data['load_check'].shift(fill_value=0).cumsum()
# print(data)
result = (
data
.groupby('load_check')
.apply(get_work_load_chunk_stat)
.reset_index(drop=True))
print(result)
Выход:
indexA total_load loads_qty indexB total_work
0 1 300 1 4 419
1 6 500 2 10 551
2 12 300 1 15 419
3 17 500 2 21 551