Группировка сравнений по месяцам с итоговыми за месяц - PullRequest
0 голосов
/ 22 января 2020

У меня есть фрейм данных (df), который выглядит следующим образом:

+----------+------------+-------------+----------+----------------
|    id    |    name    |  predicted  |  actual  |  yyyy_mm_dd   |
+----------+------------+-------------+----------+----------------
|    215   |     Nir    |     100     |   200    |  2020-01-01   |
|    215   |     Nir    |     110     |   210    |  2020-01-02   |
|    200   |     Xyc    |     120     |   220    |  2020-01-01   |
|    200   |     Xyc    |     130     |   230    |  2020-01-02   |

Выше приведено немного, мой фактический df имеет ежедневные данные за весь 2020 год, с 60 идентификаторами в день. Для будущих дат только столбцы yyyy_mm_dd, predicted и id не будут NaN. Остальные столбцы заполняются через 3 дня после наступления дня.

Я хочу добавить столбец payout. Данные в этом столбце должны быть 0, если:

  • Сумма Месяц к дате actual> = sum(predicted) для всего месяца.

Если вышеуказанное условие выполняется, тогда payout должно составлять 1% от разницы между actual и predicted

. Вот пример, показанный на рисунке:

SELECT 
    name, sum(predicted)
 FROM
     my_table
WHERE
    yyyy_mm_dd between '2020-01-01' AND '2020-01-31'
GROUP BY
    1
------------------------------------------------------
Nir, 50000
Xyc, 100000

Если «месяц до даты» actual для января <= 50000 для Nir / 100000 для Xy c, тогда <code>payout должно всегда быть 0, даже если actual> = predicted для данного дня.

Однажды 'Месяц на дату', равный actual для января> = 50000 для Nir / 100000 для Xy c, мы должны отметить payout как 1% от actual - predicted для этого дня.


Я пытался сохранить промежуточный итог в новом столбце, например:

new_sum = [df.actual.values[0]]
for i in range(1, len(df.index)):
    new_sum.append(new_sum[i-1]+df.actual.values[i])
df['actual_sum'] = new_sum

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

Я также пробовал это:

df['inc'] = df['actual'] - df['predicted']    
df['payout'] = np.where(df['inc']>=1, (df['inc'] / 100) * 1, 0)

Но приведенное выше не убедитесь, что мон ч до даты> = итого за месяц до присвоения 1%.

Редактировать : Мой ожидаемый результат - текущий df, но с дополнительным столбцом payout. Этот новый столбец должен соответствовать логике c, описанной выше.

В основном необходимо получить общее количество прогнозируемых значений за месяц. Затем добавьте ежедневную сумму actual в качестве дней пролета. По мере приближения к концу месяца значение actual должно превысить общее значение predicted за месяц. Как только этот порог будет пройден, начнется выплата, составляющая 1% от actual - predicted. До этого момента, хотя выплата равна 0. Набор данных - это ежедневные данные до конца 2020 года.

+------------+-----------+--------+------------+-------+
|  id | name | predicted | actual | yyyy_mm_dd |payout|
+------------+---------- +--------+------------+-------+
| 215 | Nir  |   100     |  200   |  2020-01-01|xxx
| 215 | Nir  |   110     |  210   |  2020-01-02|xxx
| 200 | Xyc  |   120     |  220   |  2020-01-01|xxx
| 200 | Xyc  |   130     |  230   |  2020-01-02|xxx

1 Ответ

1 голос
/ 22 января 2020

IIU C,

мы можем использовать Groupby.Transform, который позволяет вам выполнять групповые агрегации без изменения индекса, а затем использовать np.where для трансляции желаемого результата на целевой целевой кадр данных.

, поскольку вы используете календарные месяцы, это довольно просто, если вы используете собственный бизнес, розничный или финансовый календарь, то вам нужно будет настроить решение, объединив дату и время с вашим календарем.

import pandas as pd
import numpy as np

df["yyyy_mm_dd"] = pd.to_datetime(df["yyyy_mm_dd"])
m = df.groupby(['id',df['yyyy_mm_dd'].dt.month])['predicted','actual'].transform('sum')

df["inc"] = np.where(
    df["actual"] >= m["predicted"], (m["actual"] - m["predicted"]) * 0.01, 0
)

print(df)
    id          name  predicted  actual yyyy_mm_dd  inc
0  215       Nir            100     200 2020-01-01  0.0
1  215       Nir            110     210 2020-01-02  2.0
2  200       Xyc            120     220 2020-01-01  0.0
3  200       Xyc            130     230 2020-01-02  0.0

или

-

df["inc"] = np.where(
    df["actual"] >= m["predicted"], (df["actual"] - df["predicted"]) * 0.01, 0
)

print(df)

    id          name  predicted  actual yyyy_mm_dd  inc
0  215       Nir            100     200 2020-01-01  0.0
1  215       Nir            110     210 2020-01-02  1.0
2  200       Xyc            120     220 2020-01-01  0.0
3  200       Xyc            130     230 2020-01-02  0.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...