Pandas GroupBy использует другой DataFrame с горячими кодировками / перекрывающимися масками - PullRequest
0 голосов
/ 10 января 2019

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

> data_df

     a    b    c
A    1    2    1
B    0    1    3
C    0    0    1
D    2    1    1
E    1    1    1

> mask_df

    g1   g2
A    0    1
B    1    0
C    1    0
D    1    0
E    0    1

Я хочу сгруппировать и агрегировать (по сумме) значения в первом кадре данных (data_df) при условии двоичных значений (масок) во втором кадре данных (mask_df). Результат должен быть следующим (группы x функции):

> aggr_df

     a    b    c
g1   2    2    5
g2   2    3    2

Есть ли в пандах способ сгруппировать первый кадр данных (data_df), используя маски, содержащиеся во втором кадре данных (mask_df), в одну команду?

Ответы [ 5 ]

0 голосов
/ 17 января 2019

Я решил написать еще один ответ, так как:

  • coldspeed ответ работает только с однократным кодированием
  • W-B ответ не может быть легко распараллелен, поскольку он основан на понимании dict

В моем случае я заметил, что могу достичь того же результата, просто используя скалярное произведение mask_df с data_df:

> mask_df.T.dot(data_df)

В особом случае получения среднего значения вместо суммы это достижимо, масштабируя mask_df по количеству единиц для каждой группы:

> mask_df.T.dot(data_df).div(mask_df.sum(), axis=0)
0 голосов
/ 10 января 2019

Обратите внимание, что это будет работать даже в том случае, если наблюдения в первом кадре данных (data_df) принадлежат нескольким маскам во втором кадре данных (mask_df).

> pd.concat({x:data_df.mul(mask_df[x],0).sum() for x in mask_df}).unstack()

    a  b  c
g1  2  2  5
g2  2  3  2
0 голосов
/ 10 января 2019

Вот способ использования списка:

pd.DataFrame([(data_df.T * mask_df[i]).sum(axis=1) for i in mask_df.columns], 
             index = mask.columns)

    a  b  c
g1  2  2  5
g2  2  3  2
0 голосов
/ 10 января 2019

Вы можете сделать это дешево с dot и groupby:

data_df.groupby(mask_df.dot(mask_df.columns)).sum()

    a  b  c
g1  2  2  5
g2  2  3  2

Где,

mask_df.dot(mask_df.columns)

A    g2
B    g1
C    g1
D    g1
E    g2
dtype: object

Что хорошо работает, если в каждой строке всегда указан ровно один столбец 1.

0 голосов
/ 10 января 2019

Лучший способ сделать это - объединить кадры данных. Вы можете объединить индекс, используя сначала оператор соединения. df_merge = data_df.merge(aggr_df, left_on=True, right_on=True). Тогда вы можете просто использовать df_merge для операций группировки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...