Совокупная сумма с переопределениями при условииPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Совокупная сумма с переопределениями при условии

Сообщение Anonymous »

Я пытаюсь рассчитать баланс (уровень) запасов с течением времени и иметь входящие и исходящие количества в качестве входных данных (и категорию для каждого типа запасов). Обычно я рассчитываю входящие-исходящие и переношу их на следующий период (накопленная сумма), но в этом случае дополнительная сложность заключается в том, что баланс может быть переопределен в различные моменты времени, что «сбрасывает» баланс до этих значений. значения (и входящие/исходящие значения необходимо добавлять к этим переопределениям с этого момента).
Я придумал способ рассчитать это, компенсируя рассчитанный баланс (=cumsum( входящие-исходящие)) когда есть переопределенный баланс (по отрицательной рассчитанной совокупной сумме; т. е. установка инвентаря на 0, когда есть переопределенный баланс), но это не работает, когда в разное время имеется несколько переопределений.
Это мой текущий подход, который отлично работает для данного фрейма данных (= только одно переопределение () для каждой категории ())

Код: Выделить всё

>>> df = pd.DataFrame({
...   'cat': ['a', 'a', 'b', 'b', 'a', 'a', 'a', 'a', 'a', 'b'],
...   'time': [1, 2, 1, 2, 4, 5, 6, 7, 8, 9],
...   'in': [None, 10, None, None, None, 20, 11, 9, 10, None],
...   'out': [10, None, None, 20, 10, 5, None, 30, None, None],
...   'bal': [None, None, None, None, 50, None, None, None, None, None]
^ at this time, the balance should be set to 50, irrespective of prior `in` and `out`.
...  })
>>>
>>> # cumsum goes by row, so order matters
>>> df = df.sort_values(by=['time'])
>>> df
cat  time    in   out   bal
0   a     1   NaN  10.0   NaN
2   b     1   NaN   NaN   NaN
1   a     2  10.0   NaN   NaN
3   b     2   NaN  20.0   NaN
4   a     4   NaN  10.0  50.0
5   a     5  20.0   5.0   NaN
6   a     6  11.0   NaN   NaN
7   a     7   9.0  30.0   NaN
8   a     8  10.0   NaN   NaN
9   b     9   NaN   NaN   NaN
>>>
>>>
>>> # Calculate the balance as if 'bal' (the override) wasn't there (cumsum(in - out))
>>> df['inout'] = df['in'].fillna(0) - df['out'].fillna(0)
>>> df['cumsum'] = df[['cat', 'inout']].groupby(['cat']).cumsum()
>>> df
cat  time    in   out   bal  inout  cumsum
0   a     1   NaN  10.0   NaN  -10.0   -10.0
2   b     1   NaN   NaN   NaN    0.0     0.0
1   a     2  10.0   NaN   NaN   10.0     0.0
3   b     2   NaN  20.0   NaN  -20.0   -20.0
4   a     4   NaN  10.0  50.0  -10.0   -10.0   >>
>>> # Find the positions where a balance would override the calculated balance
>>> df['correction'] = -df.loc[pd.notnull(df['bal']), 'cumsum']
>>> df
cat  time    in   out   bal  inout  cumsum  correction
0   a     1   NaN  10.0   NaN  -10.0   -10.0         NaN
2   b     1   NaN   NaN   NaN    0.0     0.0         NaN
1   a     2  10.0   NaN   NaN   10.0     0.0         NaN
3   b     2   NaN  20.0   NaN  -20.0   -20.0         NaN
4   a     4   NaN  10.0  50.0  -10.0   -10.0        10.0
5   a     5  20.0   5.0   NaN   15.0     5.0         NaN
6   a     6  11.0   NaN   NaN   11.0    16.0         NaN
7   a     7   9.0  30.0   NaN  -21.0    -5.0         NaN
8   a     8  10.0   NaN   NaN   10.0     5.0         NaN
9   b     9   NaN   NaN   NaN    0.0   -20.0         NaN
>>>
>>>
>>> # Calculate with the corrected balance
>>> df['inout2'] = df['in'].fillna(0) - df['out'].fillna(0) + df['bal'].fillna(0) + df['correction'].fillna(0)
>>> df['cumsum2'] = df[['cat', 'inout2']].groupby(['cat']).cumsum()
>>> df
cat  time    in   out   bal  inout  cumsum  correction  inout2  cumsum2
0   a     1   NaN  10.0   NaN  -10.0   -10.0         NaN   -10.0    -10.0
2   b     1   NaN   NaN   NaN    0.0     0.0         NaN     0.0      0.0
1   a     2  10.0   NaN   NaN   10.0     0.0         NaN    10.0      0.0
3   b     2   NaN  20.0   NaN  -20.0   -20.0         NaN   -20.0    -20.0
4   a     4   NaN  10.0  50.0  -10.0   -10.0        10.0    50.0     50.0 (override from 'bal')
5   a     5  20.0   5.0   NaN   15.0     5.0         NaN    15.0     65.0 >>
>>>
>>> df[df['cat'] == 'a']
cat  time    in   out   bal  inout  cumsum  correction  inout2  cumsum2
0   a     1   NaN  10.0   NaN  -10.0   -10.0         NaN   -10.0    -10.0
1   a     2  10.0   NaN   NaN   10.0     0.0         NaN    10.0      0.0
4   a     4   NaN  10.0  50.0  -10.0   -10.0        10.0    50.0     50.0
5   a     5  20.0   5.0   NaN   15.0     5.0         NaN    15.0     65.0
6   a     6  11.0   NaN   NaN   11.0    16.0         NaN    11.0     76.0
7   a     7   9.0  30.0   NaN  -21.0    -5.0         NaN   -21.0     55.0
8   a     8  10.0   NaN   NaN   10.0     5.0         NaN    10.0     65.0

Выглядит неплохо. В индексе 4 простой расчет баланса переопределяется (было -10, теперь 50, как и ожидалось), и входящие потоки последующих периодов добавляются, как ожидалось.
Однако, когда я ввожу еще одно переопределение, вышеприведенный алгоритм нарушается.

Код: Выделить всё

df = pd.DataFrame({
'cat': ['a', 'a', 'b', 'b', 'a', 'a', 'a', 'a', 'a', 'b'],
'time': [1, 2, 1, 2, 4, 5, 6, 7, 8, 9],
'in': [None, 10, None, None, None, 20, 11, 9, 10, None],
'out': [10, None, None, 20, 10, 5, None, 30, None, None],
'bal': [None, None, None, None, 50, None, None, 30, None, None]
#                                                ^
})

... same pipeline as before

>>> df
cat  time    in   out   bal  inout  cumsum  correction  inout2  cumsum2
0   a     1   NaN  10.0   NaN  -10.0   -10.0         NaN   -10.0    -10.0
2   b     1   NaN   NaN   NaN    0.0     0.0         NaN     0.0      0.0
1   a     2  10.0   NaN   NaN   10.0     0.0         NaN    10.0      0.0
3   b     2   NaN  20.0   NaN  -20.0   -20.0         NaN   -20.0    -20.0
4   a     4   NaN  10.0  50.0  -10.0   -10.0        10.0    50.0     50.0  # still ok
5   a     5  20.0   5.0   NaN   15.0     5.0         NaN    15.0     65.0
6   a     6  11.0   NaN   NaN   11.0    16.0         NaN    11.0     76.0
7   a     7   9.0  30.0  30.0  -21.0    -5.0         5.0    14.0     90.0  # expect 30
8   a     8  10.0   NaN   NaN   10.0     5.0         NaN    10.0    100.0  # expect 30 + 10 = 40
9   b     9   NaN   NaN   NaN    0.0   -20.0         NaN     0.0    -20.0
Я хотел бы изменить алгоритм, чтобы сохранить простоту использования cumsum (функционал), но не могу понять, как это сделать. Это почти как если бы мне нужна условная совокупная сумма, которая заменяет промежуточные значения при выполнении условия (в данном случае, значения в bal). Однако я бы предпочел рассчитать еще один корректирующий столбец (или исправить существующий) и добавить его (но я уперся в стену, поскольку, вероятно, смотрел на него слишком долго). Любая помощь очень ценится.


Подробнее здесь: https://stackoverflow.com/questions/790 ... -condition
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»