Панды: отменить накопление (например, накопленная сумма) - PullRequest
0 голосов
/ 11 сентября 2018

Я получил данные с накопленными номерами.Есть ли умный способ деаккумулировать данные, чтобы они у меня были месяц за месяцем и не складывались друг на друга?

(посмотрите пример xlsx здесь: https://docs.google.com/spreadsheets/d/1yELrJdZmi3CFJccYSi5U6GGDW-Awp5spHDnsDyshBe0/edit?usp=sharing.)

Пример ввода:

Date    SalesRep    itemA   itemB
01-01-2018  Jakob   5       10
01-01-2018  Adomas  10      20
01-01-2018  Thomas  15      30
01-02-2018  Jakob   50      30
01-02-2018  Adomas  100     40
01-02-2018  Thomas  150     65

Желаемый вывод:

Date    SalesRep    itemA   itemB
01-01-2018  Jakob   5       10
01-01-2018  Adomas  10      20
01-01-2018  Thomas  15      30
01-02-2018  Jakob   45      20
01-02-2018  Adomas  90      20
01-02-2018  Thomas  135     35

С наилучшими пожеланиями,

Przemyslaw

PS ОБНОВЛЕНИЕ

Как насчет случая, если данные не увеличиваются каждый месяц?

Пример ввода:

Date    SalesRep    itemA   itemB
01-01-2018  Jakob   5       10
01-01-2018  Adomas  10      20
01-01-2018  Thomas  15      30
**01-02-2018    Jakob   50      30**
01-02-2018  Adomas  100     40
01-02-2018  Thomas  150     65
**01-03-2018    Jakob   50      30**
01-03-2018  Adomas  102     60
01-03-2018  Thomas  155     75

Как насчет случая Якоба, который не увеличивает каждый месяц, тогда ваши решения не работают? Могу ли я как-то указать параметры, чтобы проверить это и вычесть, только если есть изменение?

Ответы [ 3 ]

0 голосов
/ 11 сентября 2018

В основном с использованием DataFrame.groupby и diff.К сожалению, первые строки, в которых отсутствует разность предыдущих строк, nan, и это потребовало некоторой грязной очистки.Там может быть красивее путь.

df = pd.DataFrame(
    data=[
        ['01-01-2018', 'Jakob', 5, 10],
        ['01-01-2018', 'Adomas', 10, 20],
        ['01-01-2018', 'Thomas', 15, 30],
        ['01-02-2018', 'Jakob', 50, 30],
        ['01-02-2018', 'Adomas', 100, 40],
        ['01-02-2018', 'Thomas', 150, 65],
        ['01-03-2018', 'Jakob', 60, 30],
        ['01-03-2018', 'Adomas', 120, 45],
        ['01-03-2018', 'Thomas', 200, 75]
    ],
    columns=['Date', 'Sales rep', 'item A', 'item B']
)

cum_columns = ['item A', 'item B']

result = df.merge(
    df.groupby('Sales rep')[cum_columns].diff(),
    left_index=True, right_index=True, suffixes=['', '_uncum']
).fillna({'{}_uncum'.format(cum_column): df[cum_column] for cum_column in cum_columns})

print(result)
Out:
         Date Sales rep  item A  item B  item A_uncum  item B_uncum
0  01-01-2018     Jakob       5      10           5.0          10.0
1  01-01-2018    Adomas      10      20          10.0          20.0
2  01-01-2018    Thomas      15      30          15.0          30.0
3  01-02-2018     Jakob      50      30          45.0          20.0
4  01-02-2018    Adomas     100      40          90.0          20.0
5  01-02-2018    Thomas     150      65         135.0          35.0
6  01-03-2018     Jakob      60      30          10.0           0.0
7  01-03-2018    Adomas     120      45          20.0           5.0
8  01-03-2018    Thomas     200      75          50.0          10.0
0 голосов
/ 11 сентября 2018

Вот другой подход с использованием shift.Это существенно вычитает предыдущее число.Предполагается, что DataFrame уже находится в правильном порядке (сначала используйте DataFrame.sort_values, если это не так).Я думаю, что это лучше, так как дает на месте однострочник.

df = pd.DataFrame(
    data=[
        ['01-01-2018', 'Jakob', 5, 10],
        ['01-01-2018', 'Adomas', 10, 20],
        ['01-01-2018', 'Thomas', 15, 30],
        ['01-02-2018', 'Jakob', 50, 30],
        ['01-02-2018', 'Adomas', 100, 40],
        ['01-02-2018', 'Thomas', 150, 65],
        ['01-03-2018', 'Jakob', 60, 30],
        ['01-03-2018', 'Adomas', 120, 45],
        ['01-03-2018', 'Thomas', 200, 75]
    ],
    columns=['Date', 'Sales rep', 'item A', 'item B']
)

group_by_columns = ['Sales rep']
cum_columns = ['item A', 'item B']

df[cum_columns] -= df.groupby(group_by_columns)[cum_columns].shift(1).fillna(0)

print(df)
Out:
         Date Sales rep  item A  item B
0  01-01-2018     Jakob     5.0    10.0
1  01-01-2018    Adomas    10.0    20.0
2  01-01-2018    Thomas    15.0    30.0
3  01-02-2018     Jakob    45.0    20.0
4  01-02-2018    Adomas    90.0    20.0
5  01-02-2018    Thomas   135.0    35.0
6  01-03-2018     Jakob    10.0     0.0
7  01-03-2018    Adomas    20.0     5.0
8  01-03-2018    Thomas    50.0    10.0
0 голосов
/ 11 сентября 2018

Вы можете сгруппировать по торговому представителю и взять разность строк.Затем объедините наборы данных вместе.

import pandas as pd

df = pd.DataFrame({
    'Date': ['01-01-2018', '01-01-2018', '01-01-2018', '01-02-2018', '01-02-2018', '01-02-2018'],
    'SalesRep': ['Jakob', 'Adomas', 'Thomas', 'Jakob', 'Adomas', 'Thomas',],
    'itemA': [5, 10, 15, 50, 100, 150],
    'itemB': [10, 20, 30, 30, 40, 65]})

df_diff = df.groupby('SalesRep').diff().fillna(0).astype(int)
df.loc[:, ['itemA', 'itemB']] = df_diff.where(df_diff, df.loc[:, ['itemA', 'itemB']])

df
# returns:
         Date SalesRep  itemA  itemB
0  01-01-2018    Jakob      5     10
1  01-01-2018   Adomas     10     20
2  01-01-2018   Thomas     15     30
3  01-02-2018    Jakob     45     20
4  01-02-2018   Adomas     90     20
5  01-02-2018   Thomas    135     35
...