pandas groupby: * full * результат объединения групповой операции с исходным индексом - PullRequest
0 голосов
/ 02 сентября 2018

Рассмотрим это df:

import pandas as pd, numpy as np

df = pd.DataFrame.from_dict({'id': ['A', 'B', 'A', 'C', 'D', 'B', 'C'],
                            'val': [1,2,-3,1,5,6,-2], 
                            'stuff':['12','23232','13','1234','3235','3236','732323']})

Вопрос: как создать таблицу с таким количеством столбцов, сколько уникальных id ({A, B, C}) и столько строк, сколько df, где, например, для столбца, соответствующего id==A, значения:

1,
np.nan,
-2,
np.nan,
np.nan,
np.nan,
np.nan

(это результат объединения df.groupby('id')['val'].cumsum() в индексах df).

Ответы [ 4 ]

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

Коротко и просто:

df.pivot(columns='id', values='val').cumsum()
0 голосов
/ 02 сентября 2018

Уммм pivot

pd.pivot(df.index,df.id,df.val).cumsum()
Out[33]: 
id    A    B    C    D
0   1.0  NaN  NaN  NaN
1   NaN  2.0  NaN  NaN
2  -2.0  NaN  NaN  NaN
3   NaN  NaN  1.0  NaN
4   NaN  NaN  NaN  5.0
5   NaN  8.0  NaN  NaN
6   NaN  NaN -1.0  NaN
0 голосов
/ 02 сентября 2018

Конечно, более чистые ответы были предоставлены - см. Сводку.

df1 = pd.DataFrame( data = [df.id == x for x in df.id.unique()]).T.mul(df.groupby(['id']).cumsum().squeeze(),axis=0)

df1.columns =df.id.unique()
df1.applymap(lambda x: np.nan if x == 0 else x)


    A    B     C     D
0   1.0  NaN   NaN   NaN
1   NaN  2.0   NaN   NaN
2   -2.0 NaN   NaN  NaN
3   NaN  NaN   1.0   NaN
4   NaN  NaN   NaN   5.0
5   NaN  8.0   NaN   NaN
6   NaN  NaN   -1.0  NaN
0 голосов
/ 02 сентября 2018

В одну сторону через словарь и pd.DataFrame.where:

res = pd.DataFrame({i: df['val'].where(df['id'].eq(i)).cumsum() for i in df['id'].unique()})

print(res)

     A    B    C    D
0  1.0  NaN  NaN  NaN
1  NaN  2.0  NaN  NaN
2 -2.0  NaN  NaN  NaN
3  NaN  NaN  1.0  NaN
4  NaN  NaN  NaN  5.0
5  NaN  8.0  NaN  NaN
6  NaN  NaN -1.0  NaN

Для небольшого числа групп этот метод может оказаться эффективным:

df = pd.concat([df]*1000, ignore_index=True)

def piv_transform(df):
    return pd.pivot(df.index, df.id, df.val).cumsum()

def dict_transform(df):
    return pd.DataFrame({i: df['val'].where(df['id'].eq(i)).cumsum() for i in df['id'].unique()})

%timeit piv_transform(df)   # 17.5 ms
%timeit dict_transform(df)  # 8.1 ms
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...