Эффективно сравнить промежуточные итоги за месяц с итоговыми за месяц - PullRequest
2 голосов
/ 23 января 2020

У меня есть датафрейм (df). Он содержит predicted суточных данных из модели вплоть до конца 2020 года. По мере того, как каждый год проходит в году, в строку добавляются данные actual и id. Для каждого дня есть несколько имен

+------+-----+-----------+--------+------------+
| NAME | ID  | PREDICTED | ACTUAL | YYYY_MM_DD |
+------+-----+-----------+--------+------------+
| Nir  | 215 | 100       | 400    | 2020-01-01 |
| Nir  | 215 | 200       | 400    | 2020-01-02 |
| Nir  | 215 | 100       | 400    | 2020-01-03 |
| Nir  | 215 | 200       | 400    | 2020-01-04 |
| Nir  | 215 | 100       | 400    | 2020-01-05 |
| Nir  | 215 | 200       | 400    | 2020-01-06 |
| Nir  | 215 | 100       | 400    | 2020-01-07 |
| Nir  | 215 | 200       | 400    | 2020-01-08 |
| Nir  | 215 | 100       | 400    | 2020-01-09 |
| Nir  | 215 | 200       | 400    | 2020-01-10 |
| Nir  | 215 | 100       | 400    | 2020-01-11 |
| Nir  | 215 | 200       | 400    | 2020-01-12 |
| Nir  | 215 | 100       | 400    | 2020-01-13 |
| Nir  | 215 | 200       | 400    | 2020-01-14 |
| Nir  | 215 | 100       | 400    | 2020-01-15 |
| Nir  | 215 | 200       | 400    | 2020-01-16 |
| Nir  | 215 | 100       | 400    | 2020-01-17 |
| Nir  | 215 | 200       | 400    | 2020-01-18 |
| Nir  | 215 | 100       | 400    | 2020-01-19 |
| Nir  | 215 | 200       | 400    | 2020-01-20 |
| Nir  | 215 | 100       | 400    | 2020-01-21 |
| Nir  | 215 | 200       | 400    | 2020-01-22 |
| Nir  | 215 | 100       | 400    | 2020-01-23 |
| Nir  | Nan | 100       | Nan    | 2020-01-24 |
| Nir  | Nan | 100       | Nan    | 2020-01-25 |
| Nir  | Nan | 100       | Nan    | 2020-01-26 |
| Nir  | Nan | 100       | Nan    | 2020-01-27 |
| Nir  | Nan | 100       | Nan    | 2020-01-28 |
| Nir  | Nan | 100       | Nan    | 2020-01-29 |
| Nir  | Nan | 100       | Nan    | 2020-01-30 |
| Nir  | Nan | 100       | Nan    | 2020-01-31 |
| Xyc  | 40  | 800       | 500    | 2020-01-01 |
| Xyc  | 40  | 100       | 500    | 2020-01-02 |
| Xyc  | 40  | 100       | 500    | 2020-01-03 |
| Xyc  | 40  | 100       | 500    | 2020-01-04 |
| ...  | ... | ...       | ...    | ...        |
| ...  | ... | ...       | ...    | ...        |
+------+-----+-----------+--------+------------+

Я хочу добавить дополнительный столбец с именем payout. payout должно быть 0, если сумма actual, за месяц к дате не прошла сумму predicted.

То есть, для Nir мы можем увидеть сумму predicted 4200. Таким образом, payout должно быть 0, пока сумма actual не пройдет 4200. Как только этот порог пройден, тогда payout должен составлять 1% от actual-predicted. С вышеуказанными данными результат будет выглядеть следующим образом:

+------+-----+-----------+--------+---------------+--------+------------+
| NAME | ID  | PREDICTED | ACTUAL | MONTH_TO_DATE | PAYOUT | YYYY_MM_DD |
+------+-----+-----------+--------+---------------+--------+------------+
| Nir  | 215 | 100       | 400    | 400           | 0      | 2020-01-01 |
| Nir  | 215 | 200       | 400    | 800           | 0      | 2020-01-02 |
| Nir  | 215 | 100       | 400    | 1200          | 0      | 2020-01-03 |
| Nir  | 215 | 200       | 400    | 1600          | 0      | 2020-01-04 |
| Nir  | 215 | 100       | 400    | 2000          | 0      | 2020-01-05 |
| Nir  | 215 | 200       | 400    | 2400          | 0      | 2020-01-06 |
| Nir  | 215 | 100       | 400    | 2800          | 0      | 2020-01-07 |
| Nir  | 215 | 200       | 400    | 3200          | 0      | 2020-01-08 |
| Nir  | 215 | 100       | 400    | 3600          | 0      | 2020-01-09 |
| Nir  | 215 | 200       | 400    | 4000          | 0      | 2020-01-10 |
| Nir  | 215 | 100       | 400    | 4400          | 3      | 2020-01-11 |
| Nir  | 215 | 200       | 400    | ...           | 2      | 2020-01-12 |
| Nir  | 215 | 100       | 400    | ...           | 3      | 2020-01-13 |
| Nir  | 215 | 200       | 400    | ...           | 2      | 2020-01-14 |
| Nir  | 215 | 100       | 400    | ...           | 3      | 2020-01-15 |
| Nir  | 215 | 200       | 400    | ...           | 2      | 2020-01-16 |
| Nir  | 215 | 100       | 400    | ...           | 3      | 2020-01-17 |
| Nir  | 215 | 200       | 400    | ...           | 2      | 2020-01-18 |
| Nir  | 215 | 100       | 400    | ...           | 3      | 2020-01-19 |
| Nir  | 215 | 200       | 400    | ...           | 2      | 2020-01-20 |
| Nir  | 215 | 100       | 400    | ...           | 3      | 2020-01-21 |
| Nir  | 215 | 200       | 400    | ...           | 2      | 2020-01-22 |
| Nir  | 215 | 100       | 400    | ...           | 3      | 2020-01-23 |
| Nir  | Nan | 100       | Nan    |               |        | 2020-01-24 |
| Nir  | Nan | 100       | Nan    |               |        | 2020-01-25 |
| Nir  | Nan | 100       | Nan    |               |        | 2020-01-26 |
| Nir  | Nan | 100       | Nan    |               |        | 2020-01-27 |
| Nir  | Nan | 100       | Nan    |               |        | 2020-01-28 |
| Nir  | Nan | 100       | Nan    |               |        | 2020-01-29 |
| Nir  | Nan | 100       | Nan    |               |        | 2020-01-30 |
| Nir  | Nan | 100       | Nan    |               |        | 2020-01-31 |
| Xyc  | 40  | 800       | 500    | 500           | 0      | 2020-01-01 |
| Xyc  | 40  | 100       | 500    | 1000          | 0      | 2020-01-02 |
| Xyc  | 40  | 100       | 500    | 1500          | 4      | 2020-01-03 |
| Xyc  | 40  | 100       | 500    | 2000          | 4      | 2020-01-04 |
| ...  | ... | ...       | ...    |               |        | ...        |
| ...  | ... | ...       | ...    |               |        | ...        |
+------+-----+-----------+--------+---------------+--------+------------+

В приведенном выше выводе Xyc имеет общее прогнозируемое значение 2000, поэтому payout должно быть равно 0, пока сумма не пройдет actual. 2000 также. В реальных данных есть ежедневные данные за ~ 70 name с, поэтому я чувствую, что может потребоваться группировка.


Я пробовал:

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 

Однако это просто дало мне итоговую сумму actual. Я также попробовал это:

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

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

1 Ответ

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

Сначала Вам нужно удалить из данных NaN-строки.

Здесь Вы go:

import pandas as pd
import numpy as np


df = pd.DataFrame({'Name':['Nir','Nir','Nir','Nir','Xyc','Xyc','Xyc'],'PREDICTED':[100,200,100,200,100,200,300],
                   'ACTUAL':[400,400,400,400,500,500,500],
                   'YYYY_MM_DD':['2020-01-01','2020-01-02','2020-01-03','2020-01-04','2020-01-01','2020-01-02','2020-01-03']})


def calculate(item):
    # select name
    data = df[df['Name'] == item]
    # calculate sum
    sum = data['PREDICTED'].sum()

    # remove NaN rows
    data = data.dropna()

    # calculate and insert  month to date column values
    month_to_date = []
    value = 0
    for index, row in data.iterrows():
        value += row['ACTUAL']
        month_to_date.append(value)

    data.insert(3, "MONTH_TO_DATE", month_to_date, True)

    # calculate and instert payout values
    conditions = [
        (data['MONTH_TO_DATE'] < sum),
        (data['MONTH_TO_DATE'] >= sum)
    ]
    choices = [0, ((data['ACTUAL'] - data['PREDICTED'])/100).astype(int)]
    data.insert(5, "PAYOUT", np.select(conditions, choices), True)

    return data


# collect results
results = pd.DataFrame(columns=['Name','PREDICTED','ACTUAL','MONTH_TO_DATE','YYYY_MM_DD','PAYOUT'])

for item in df['Name'].unique():
    df2 = calculate(item)
    results = results.append(df2)

Результат:

  Name PREDICTED ACTUAL MONTH_TO_DATE  YYYY_MM_DD PAYOUT
0  Nir       100    400           400  2020-01-01      0
1  Nir       200    400           800  2020-01-02      2
2  Nir       100    400          1200  2020-01-03      3
3  Nir       200    400          1600  2020-01-04      2
4  Xyc       100    500           500  2020-01-01      0
5  Xyc       200    500          1000  2020-01-02      3
6  Xyc       300    500          1500  2020-01-03      2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...