Условный счетчик хода в пандах только для всех предыдущих рядов - PullRequest
1 голос
/ 23 сентября 2019

Предположим, у меня есть следующий DataFrame:

df = pd.DataFrame({'Event': ['A', 'B', 'A', 'A', 'B', 'C', 'B', 'B', 'A', 'C'], 
                    'Date': ['2019-01-01', '2019-02-01', '2019-03-01', '2019-03-01', '2019-02-15', 
                             '2019-03-15', '2019-04-05', '2019-04-05', '2019-04-15', '2019-06-10'],
                    'Sale':[100,200,150,200,150,100,300,250,500,400]})
df['Date'] = pd.to_datetime(df['Date'])
df

Event         Date
    A   2019-01-01
    B   2019-02-01
    A   2019-03-01
    A   2019-03-01
    B   2019-02-15
    C   2019-03-15
    B   2019-04-05
    B   2019-04-05
    A   2019-04-15
    C   2019-06-10

Я хотел бы получить следующий результат:

Event         Date  Previous_Event_Count
    A   2019-01-01                     0
    B   2019-02-01                     0
    A   2019-03-01                     1
    A   2019-03-01                     1
    B   2019-02-15                     1
    C   2019-03-15                     0
    B   2019-04-05                     2
    B   2019-04-05                     2
    A   2019-04-15                     3
    C   2019-06-10                     1

, где df['Previous_Event_Count'] - номер события (строки)когда событие (df['Event']) происходит до его смежной даты (df['Date']).Например,

  • Номер события A, произошедшего до 2019-01-01, равен 0,
  • Номер события A, предшествующего 2019-03-01, равен 1,и
  • Число событий A, происходящих до 2019-04-15, равно 3.

Я могу получить желаемый результат, используя эту строку:

df['Previous_Event_Count'] = [df.loc[(df.loc[i, 'Event'] == df['Event']) & (df.loc[i, 'Date'] > df['Date']), 
                                     'Date'].count() for i in range(len(df))]

Хотя это медленно, но работает нормально.Я считаю, что есть лучший способ сделать это.Я пробовал эту строку:

df['Previous_Event_Count'] = df.query('Date < Date').groupby(['Event', 'Date']).cumcount()

, но он производит NaN.

Ответы [ 3 ]

2 голосов
/ 24 сентября 2019

Сначала подсчитайте по GroupBy.size для каждого столбца, затем агрегируйте по первому уровню с shift и совокупной суммой и последним join до исходного значения:

s = (df.groupby(['Event', 'Date'])
       .size()
       .groupby(level=0)
       .apply(lambda x: x.shift(1).cumsum())
       .fillna(0)
       .astype(int))

df = df.join(s.rename('Previous_Event_Count'), on=['Event','Date'])
print (df)
  Event       Date  Previous_Event_Count
0     A 2019-01-01                     0
1     B 2019-02-01                     0
2     A 2019-03-01                     1
3     A 2019-03-01                     1
4     B 2019-02-15                     1
5     C 2019-03-15                     0
6     B 2019-04-05                     2
7     B 2019-04-05                     2
8     A 2019-04-15                     3
9     C 2019-06-10                     1
2 голосов
/ 23 сентября 2019

groupby + rank

Даты можно рассматривать как числовые.Используйте 'min' для получения логики подсчета.

df['PEC'] = (df.groupby('Event').Date.rank(method='min')-1).astype(int)

  Event       Date  PEC
0     A 2019-01-01    0
1     B 2019-02-01    0
2     A 2019-03-01    1
3     A 2019-03-01    1
4     B 2019-02-15    1
5     C 2019-03-15    0
6     B 2019-04-05    2
7     B 2019-04-05    2
8     A 2019-04-15    3
9     C 2019-06-10    1
0 голосов
/ 24 сентября 2019

Наконец, я могу найти лучший и быстрый способ получить желаемый результат.Оказывается, это очень просто.Можно попробовать:

df['Total_Previous_Sale'] = df.groupby('Event').cumcount() \
                          - df.groupby(['Event', 'Date']).cumcount()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...