Recosh
@Recosh
Программист студент

Как в pandas посчитать только новые данные, а не всю таблицу?

Допустим есть табличка:
import pandas as pd
data = {
    'one': list(range(2, 15, 4)),
    'two': list(range(4, 16, 3))
}
df = pd.DataFrame(data)
df

-	one	two
0	2	4
1	6	7
2	10	10
3	14	13


Есть метод обработки данных:
def compute(df):
  df['rol1'] = df.rolling(3, min_periods=1).one.mean()
  df['rol2'] = df.rolling(3, min_periods=1).two.quantile(0.5)
  df['rol3'] = df.rolling(2, min_periods=1).rol2.min()
  return df

df = compute(df)
df

В результате получаем:
-	one	two	rol1	rol2	rol3
0	2	4	2.0	4.0	4.0
1	6	7	4.0	5.5	4.0
2	10	10	6.0	7.0	5.5
3	14	13	10.0	10.0	7.0

Отлично, а теперь после этого добавляется новая строка, допустим так:
newData = {'one': 13, 'two': 6}
df = df.append(newData, ignore_index=True)
df

В итоге добавляется строчка, а в остальных полях NaN
-	one	two	rol1	rol2	rol3
0	2.0	4.0	2.0	4.0	4.0
1	6.0	7.0	4.0	5.5	4.0
2	10.0	10.0	6.0	7.0	5.5
3	14.0	13.0	10.0	10.0	7.0
4	13.0	6.0	NaN	NaN	NaN


Как теперь сказать pandas, что бы он посчитал только данные для последней строчки? Потому что если я снова вызову df = compute(df) он пересчитает всю таблицу. А при больших данных это довольно много времени, а я хотел бы работать с данными в реальном времени.
Есть вариант создать функцию копию и вместо rolling использовать tail, но делать копи паст одной и той же логики не хочется. Итоговый алгоритм в моей программе получается сложным и дублировать его тоже не хочется.
Заранее спасибо за ответ!)
  • Вопрос задан
  • 96 просмотров
Пригласить эксперта
Ответы на вопрос 2
@sunsexsurf
IT & creative
Сходу пандас так не умеет.
Я бы добавил столбец, в котором записывал бы флаг "1/0" и для "старых" данных устанавливал бы флаг 1, для новых - функция бы возвращала 0
И тогда вам достаточно применить фильтр по последнему столбцу
после пересчета поменять флаг на 1
UPD: вариант "хранить копию и измененную таблицу сравнивать с копией" не рассматриваем ввиду ваших "тяжелых" рассчетов (порой, реально в память не помещается)
Ответ написан
trapwalker
@trapwalker Куратор тега Python
Программист, энтузиаст
Держите два датафрейма:
Один по размеру окна и при добавлении в него строчки в хвост удаляйте одну из головы.
Второй накопительный, дуда добавляйте посчитанное. Так вы сохраните один и тот же код и для массовой обработки накопленных данных и для оконной риалтаймовой.
Но тоже не очень эффективно, особенно при большом размере окна.

Второй вариант - это реализовать свою оконную функцию, грубо говоря это будет объект с состоянием, куда построчно заталкиваются и соответственно извлекаются данные. Объект внутри хранит оконный буфер, но считает всё сам, без панды и выщёлкивает из буфера ненужные строки.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы