Pandas групповые пользовательские группы - PullRequest
2 голосов
/ 22 января 2020

Допустим, у меня есть такой фрейм данных:

df = pd.DataFrame({'A': [1, 2, 3, 4, 5, 6], 'B': ['a', 'a', 'b', 'b', 'c', 'c']})
print(df)

   A  B
0  1  a
1  2  a
2  3  b
3  4  b
4  5  c
5  6  c

Как я могу сгруппировать по col B, чтобы группы были a, a OR b и a OR b OR c, а не просто a, b и c? Для примера скажем, что я хочу агрегировать результаты по 'sum'. Я бы тогда закончил с:

              A
a             3
a OR b        10 
a OR b OR c   21

1 Ответ

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

Я думаю, что это действительно зависит от функции, которую вы хотите использовать. Я могу придумать трюк с DataFrame.expanding, например, если вы хотите вычислить сумму . Идея состоит в том, что мы можем воспользоваться преимуществами расширения, а затем принять во внимание только строки, где целые группы были выбраны с Series.where

df.expanding().sum().where(df['B'].ne(df['B'].shift(-1)))
      A
0   NaN
1   3.0
2   NaN
3  10.0
4   NaN
5  21.0

df.expanding().sum().where(df['B'].ne(df['B'].shift(-1))).loc[lambda x: x.A.notna()]

      A
1   3.0
3  10.0
5  21.0

ОБНОВЛЕНО

Мы также можем использовать DataFrame.groupby + DataFrame.expanding

df.groupby('B').sum().expanding().sum()

Чтобы получить ожидаемый результат:

new_df = (df.groupby('B').sum().expanding().sum()
            .reset_index()
            .assign(B = lambda x: x.B.add(' or ').cumsum()
                                  .str.rstrip(' or '))
            .set_index('B') )
print(new_df)
                A
B                
a             3.0
a or b       10.0
a or b or c  21.0
...