Как при вычислении столбца получить предыдущее его значение в pandas?

Стоит задача: в столбце 'Плановый остаток' вычислить значения по следующей логике: Если Дата=='2024-01-01, то значение берется из столбца 'Остаток на начало расчета' (далее прибавляется плановый приход и вычитается продажи 'Продажи + сезонность + рост') Иначе берется значение в столбце 'Плановый остаток' предыдущего дня (например для вычисления на дату 2024-01-20 остаток возьмется из предыдущей строки - 2024-01-19) далее прибавляется плановый приход и вычитается продажи 'Продажи + сезонность + рост'.

Формула из excel(если кому будет понятнее):

# =ЕСЛИМН(
#     Расчет!A76124=ДАТАЗНАЧ("01.01.2024");     # Если дата = 01.01.2024,
#     ВПР(                                      ВПРится остаток из таблицы базовых значений
#         C76124;                        Суммируется с приходом за этот день
#         'Базовые значения'!A:G;               и вычитается [Продажи + сезонность + рост]
#         7;
#         0
#     )+M76124-K76124;                   # Если дата > 01.01.2024,
#     A76124>ДАТАЗНАЧ("01.01.2024");            Остаток на день раньше суммируется с
#     ЕСЛИ(                                     приходим за этот день и вычитается
#         L76123+M76124-K76124<0;               [Продажи + сезонность + рост]
#         0;                                    Если полученное выражение < 0
#         L76123+M76124-K76124                  то значение = 0, иначе полученное значение
#     )
# )

Часть данных для примера:

df_calculation = pd.DataFrame({"Артикул":{"191808":"99156","191809":"99156","191810":"99156","191811":"99156","191812":"99156","191813":"99156","191814":"99156","191815":"99156","191816":"99156","191817":"99156"},"Наименование":{"191808":"name","191809":"name","191810":"name","191811":"name","191812":"name","191813":"name","191814":"name","191815":"name","191816":"name","191817":"name"},"Группа":{"191808":"Группа 1","191810":"Группа 1","191812":"Группа 1","191813":"Группа 1","191814":"Группа 1","191815":"Группа 1","191816":"Группа 1","191817":"Группа 1"},"Ид категории ВБ":{"191808":67,"191809":67,"191810":67,"191811":67,"191812":67,"191813":67,"191814":67,"191815":67,"191816":67,"191817":67},"Ц.З.WB Текущая":{"191808":3149,"191809":3149,"191810":3149,"191811":3149,"191812":3149,"191813":3149,"191814":3149,"191815":3149,"191816":3149,"191817":3149},"Средние продажи":{"191808":100,"191809":100,"191810":100,"191811":100,"191812":100,"191813":100,"191814":100,"191815":100,"191816":100,"191817":100},"Базовые продажи для расчета (Август-Сентябрь-Октябрь 2023)+ корректировки":{"191808":3000,"191809":3000,"191810":3000,"191811":3000,"191812":3000,"191813":3000,"191814":3000,"191815":3000,"191816":3000,"191817":3000},"Остаток на начало отсчета":{"191808":1000,"191809":1000,"191810":1000,"191811":1000,"191812":1000,"191813":1000,"191814":1000,"191815":1000,"191816":1000,"191817":1000},"Дата":{"191808":1704067200000,"191809":1704153600000,"191810":1704240000000,"191811":1704326400000,"191812":1704412800000,"191813":1704499200000,"191814":1704585600000,"191815":1704672000000,"191816":1704758400000,"191817":1704844800000},"Общая сезонность выручки":{"191808":0.7263,"191809":0.9784,"191810":0.8993,"191811":0.9551,"191812":1.0019,"191813":1.0221,"191814":1.0871,"191815":1.0625,"191816":1.0951,"191817":1.0093},"Общая сезонность продаж":{"191808":0.7276,"191809":0.9945,"191810":0.9304,"191811":0.9855,"191812":1.0271,"191813":0.9888,"191814":1.0273,"191815":1.1154,"191816":1.0645,"191817":1.0295},"К.роста":{"191808":0.0000022334,"191809":0.0000044669,"191810":0.0000067003,"191811":0.0000089338,"191812":0.0000111672,"191813":0.0000134006,"191814":0.0000156341,"191815":0.0000178675,"191816":0.000020101,"191817":0.0000223344},"Продажи + сезонность":{"191808":73.0,"191809":99.0,"191810":93.0,"191811":99.0,"191812":103.0,"191813":99.0,"191814":103.0,"191815":112.0,"191816":106.0,"191817":103.0},"Продажи + сезонность + рост":{"191808":73.0819627462,"191809":99.1639254925,"191810":93.2458882387,"191811":99.3278509849,"191812":103.4098137312,"191813":99.4917764774,"191814":103.5737392237,"191815":112.6557019699,"191816":106.7376647161,"191817":103.8196274624},"План прихода":{"191808":0.0,"191809":0.0,"191810":0.0,"191811":0.0,"191812":0.0,"191813":0.0,"191814":0.0,"191815":0.0,"191816":1908.0,"191817":0.0}})

Вычисления которые производились:

df_calculation['Продажи + сезонность'] = (df_calculation['Средние продажи'] * df_calculation['Общая сезонность продаж']).round(0)
df_calculation['Продажи + сезонность + рост'] = df_calculation['К.роста']*df_calculation.groupby('Артикул')['Продажи + сезонность'].transform('sum') + df_calculation['Продажи + сезонность']
df_calculation = df_calculation.set_index(['Артикул', 'Дата'])

condition = df_calculation.index.get_level_values('Дата') == '2024-01-01'

df_calculation['План остатков'] = df_calculation.loc[condition, 'Остаток на начало отсчета'] + df_calculation.loc[condition, 'План прихода'] - df_calculation.loc[condition, 'Продажи + сезонность + рост']

# Пробовал так
# df_calculation['План остатков'] = df_calculation['План остатков'].fillna(
    # df_calculation.loc[~condition, 'План остатков'].shift(-1) + df_calculation.loc[~condition, 'План прихода'] - df_calculation.loc[~condition, 'Продажи + сезонность + рост'])
    или так
# df_calculation['План остатков'] = df_calculation['План остатков'].fillna(df_calculation.loc[~condition, 'План остатков'].shift(-1) + df_calculation.loc[~condition, 'План прихода'] + df_calculation.loc[~condition, 'Продажи + сезонность + рост'])

К сожалению оба варианта не дали желаемого результата. Подскажите как можно решить? (хотелось бы обойтись без цикла)

P.S. Использовав предложенный вариант в целом поведение правильное, но когда остаток достигает <0, то расчет не правильный, в чем может быть причина? Фрейм данных:

df_calculate = pd.read_csv('https://raw.githubusercontent.com/Rett-oo/test/main/test.csv')

код который я поправил, мне нужны данные остатков только на начало года(насколько я понял от этого условия зависит откуда берется остаток)

df_calculation['План остатков'] = df_calculation[df_calculation["Дата"].dt.is_year_start].apply(lambda x: x['Остаток на начало отсчета'] + x['План прихода'] - x['Продажи + сезонность + рост'], axis=
df_calculation["План остатков"] = df_calculation.groupby(df_calculation["Дата"].dt.is_year_start.cumsum())["План остатков"].cumsum()

Ответы (1 шт):

Автор решения: strawdog

совсем уж элегантно не получилось, но можно попробовать так

UPDATE

в связи с тем, что должна происходить ещё и группировка по артикулу, решение принимает следующий вид:

import pandas as pd

df = pd.read_csv('https://raw.githubusercontent.com/Rett-oo/test/main/test.csv', usecols=[0,7,8,11,12,13,14])
df = df.iloc[:25,:]
df["Дата"] = pd.to_datetime(df["Дата"])
df['План остатков'] = df[df["Дата"].dt.is_year_start].apply(lambda x: x['Остаток на начало отсчета'] + x['План прихода'] - x['Продажи + сезонность + рост'], axis=1)
df['План остатков'] = df.groupby("Артикул")['План остатков'].fillna(df['План прихода'] - df['Продажи + сезонность + рост'])
df['План остатков'] = df.groupby(df["Артикул"], as_index=False).apply(lambda x: x.groupby(x["Дата"].dt.is_year_start.cumsum())["План остатков"].cumsum(), include_groups=False).reset_index(drop=True)

df:

    Артикул  Остаток на начало отсчета       Дата   К.роста  Продажи + сезонность  Продажи + сезонность + рост  План прихода  План остатков
0      7010                        500 2024-01-01  0.000002                  38.0                    38.047188           0.0     461.952812
1     99156                       1000 2024-01-01  0.000002                  73.0                    73.081963           0.0     407.858436
2     99156                       1000 2024-01-02  0.000004                  99.0                    99.163925           0.0     356.716871
3      7010                        500 2024-01-02  0.000004                  54.0                    54.094376           0.0     302.528119
4     99156                       1000 2024-01-03  0.000007                  93.0                    93.245888           0.0     248.292178
5      7010                        500 2024-01-03  0.000007                  51.0                    51.141564           0.0     194.009050
6      7010                        500 2024-01-04  0.000009                  54.0                    54.188752           0.0     138.678733
7     99156                       1000 2024-01-04  0.000009                  99.0                    99.327851           0.0      88.301228
8      7010                        500 2024-01-05  0.000011                  54.0                    54.235941           0.0      35.876535
9     99156                       1000 2024-01-05  0.000011                 103.0                   103.409814           0.0     -22.595346
10    99156                       1000 2024-01-06  0.000013                  99.0                    99.491776           0.0     -90.114415
11     7010                        500 2024-01-06  0.000013                  54.0                    54.283129           0.0    -154.680672
12     7010                        500 2024-01-07  0.000016                  55.0                    55.330317           0.0     926.918037
13    99156                       1000 2024-01-07  0.000016                 103.0                   103.573739           0.0     827.754112
14     7010                        500 2024-01-08  0.000018                  50.0                    50.377505           0.0     734.508224
15    99156                       1000 2024-01-08  0.000018                 112.0                   112.655702           0.0     635.180373
16     7010                        500 2024-01-09  0.000020                  52.0                    52.424693           0.0     531.770559
17    99156                       1000 2024-01-09  0.000020                 106.0                   106.737665           0.0     432.278782
18    99156                       1000 2024-01-10  0.000022                 103.0                   103.819627           0.0     328.705043
19     7010                        500 2024-01-10  0.000022                  58.0                    58.471881           0.0     216.049341
20     7010                        500 2024-01-11  0.000025                  67.0                    67.519069           0.0     109.311676
21    99156                       1000 2024-01-11  0.000025                 105.0                   105.901590           0.0       5.492049
22     7010                        500 2024-01-12  0.000027                  64.0                    64.566257           0.0    -100.409541
23    99156                       1000 2024-01-12  0.000027                 103.0                   103.983553           0.0    -204.393094
24    99156                       1000 2024-01-13  0.000029                  97.0                    98.065516           0.0    -302.458610
→ Ссылка