Pandas Инвертирование кумулятивного счета - PullRequest
1 голос
/ 09 июля 2020

Мне дан фрейм данных с совокупными данными подсчета. Пример генерируется следующим образом (не стесняйтесь пропустить:

import numpy as np
import pandas as pd

cols = ['Start', 'End', 'Count']
data = np.array([
    '2020-1-1', '2020-1-2',      4,
    '2020-1-1', '2020-1-3',      6,
    '2020-1-1', '2020-1-4',      8,
    '2020-2-1', '2020-2-2',      3,
    '2020-2-1', '2020-2-3',      4,
    '2020-2-1', '2020-2-4',      4])
data = data.reshape((6,3))
df = pd.DataFrame(columns=cols, data=data)
df['Start'] = pd.to_datetime(df.Start)
df['End'] = pd.to_datetime(df.End)

Это дает следующий фрейм данных:

Start        End      Count
2020-1-1 2020-1-2      4
2020-1-1 2020-1-3      6
2020-1-1 2020-1-4      8
2020-2-1 2020-2-2      3
2020-2-1 2020-2-3      4
2020-2-1 2020-2-4      4

Счетчики являются кумулятивными (накопление начинается при запуске), и я хочу отмените накопление, чтобы получить (обратите внимание на изменение дат):

Start        End      Count
2020-1-1 2020-1-2      4
2020-1-2 2020-1-3      2
2020-1-3 2020-1-4      2
2020-2-1 2020-2-2      3
2020-2-2 2020-2-3      1
2020-2-3 2020-2-4      0

Я хотел бы сделать это для сгруппированных переменных. Это можно наивно сделать следующим образом:

lst = []
for start, data in df.groupby(['Start', 'grouping_variable']):
    data = data.sort_values('End')
    diff = data.Count.diff()
    diff.iloc[0] = data.Count.iloc[0]
    start_dates = [data.Start.iloc[0]] + list(data.end[:-1].values)
    data = data.assign(Start=start_dates,
                       Count=diff)

    lst.append(data)


df = pd.concat(lst)

Это действительно не чувствую себя «правильным», «pythoni c» или «чистым». Есть ли лучший способ? Возможно, Pandas имеет специальный метод c для этого?

1 Ответ

1 голос
/ 09 июля 2020

IIU C, мы можем использовать cumcount с логическим значением для захвата каждой уникальной группы начальной даты, а затем применить операцию np.where, используя shift для каждой группы.

import numpy as np
#df['Count'] = df['Count'].astype(int)

s = df.groupby(['Start']).cumcount() == 0
df['Count'] = np.where(s,df['Count'],df['Count'] - df['Count'].shift())
df['Start'] = np.where(s, df['Start'], df['End'].shift(1))
    

print(df)
       Start        End  Count
0 2020-01-01 2020-01-02    4.0
1 2020-01-02 2020-01-03    2.0
2 2020-01-03 2020-01-04    2.0
3 2020-02-01 2020-02-02    3.0
4 2020-02-02 2020-02-03    1.0
5 2020-02-03 2020-02-04    0.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...