pandas split-apply-Объединить с результатами, возвращенными в исходный DataFrame - PullRequest
0 голосов
/ 17 декабря 2018

Я хочу задокументировать конкретный случай использования метода 'split-apply-Объединить' .

Проблема: я начинаю с DataFrame, и мне нужно выполнить некоторую обработку данных, которая требует разделения по группам и возвращает некоторые результаты.Далее давайте предположим, что обработка не может быть выполнена простой встроенной операцией (для этого есть ярлыки), но она достаточно сложна, чтобы мне пришлось проходить по группам.Кроме того, я хочу, чтобы результаты были возвращены в исходный DataFrame.(Да, я знаю, если результатом будет единственный скаляр для всей группы, я буду тратить память. Однако часто я хочу, чтобы эти результаты были в исходной таблице данных, а не иметь дело с другимиТаблица).

Я обнаружил, что этот случай плохо документирован как в документации для панд, так и здесь.

Давайте проиллюстрируем на примере:

import pandas as pd
import numpy as np

# Prepare DataFrame
data = {'Group':['A']*4+['B']*4+['C']*4,'Prop1':['S1','S2','S3','S4','S5','S6','S7','S8','S9','S10',
'S11','S12'],'Prop2':[2004,2004,3004,3004,4004,4004,5004,5004,6004,6004,7004,7004],
'Res1':[0,1,2,3,10,11,12,13,20,21,22,23]}
df = pd.DataFrame(data=data)
df

Initial DataFrane

Теперь мы продолжим работу с групповыми операциями и вычисление новогоРезультаты:

df['Res2'] = np.nan
df['Res3'] = np.nan
grouped = df.groupby('Group')
for (key,gr) in grouped:
    # Calculate two new results based on gr values
    res2 = gr['Res1'].mean()
    gr['Res2'] = res2
    res3 = gr['Prop2'] + gr['Res1']
    gr['Res3'] = res3
    # At this point gr has two new columns Res2 and Res3
    # Now we need to copy those changes back to the original DataFrame df
    df.update(gr)

Сложная задача - вернуть результаты в df.Обратите внимание, что мне сначала нужно было создать два новых столбца в df, иначе это не сработало бы.Первый способ - использовать команду .update.Это легко читать.Используя команду %timeit, я рассчитал это время (1,85 мс, 1,84 мс, 1,74 мс).

Второй способ сделать то же самое - заметить, что исходный индекс сохраняется в gr.Таким образом, мы можем просто заменить df.update(gr) на:

df.loc[gr.index,('Res2','Res3')] = gr[['Res2','Res3']]

После того, как любая из этих ячеек, мы получим желаемый результат (вместе с пресловутым SettingWithCopy предупреждением):

final result

Интересно, что второй метод немного быстрее, время (1,66 мс, 1,69 мс, 1,73 мс).

У меня есть вопрос, есть липроще?И как это сделать для DataFrame с мультииндексом строки?

1 Ответ

0 голосов
/ 17 декабря 2018

Вы можете использовать преобразование для Res2, а Res3 - просто сумма.Нет необходимости создавать два новых столбца

df['Res2'] = df.groupby('Group').Res1.transform('mean')
df['Res3'] = df['Prop2'] + df['Res1']

    Group   Prop1   Prop2   Res1    Res2    Res3
0   A   S1  2004    0   1.5     2004
1   A   S2  2004    1   1.5     2005
2   A   S3  3004    2   1.5     3006
3   A   S4  3004    3   1.5     3007
4   B   S5  4004    10  11.5    4014
5   B   S6  4004    11  11.5    4015
6   B   S7  5004    12  11.5    5016
7   B   S8  5004    13  11.5    5017
8   C   S9  6004    20  21.5    6024
9   C   S10 6004    21  21.5    6025
10  C   S11 7004    22  21.5    7026
11  C   S12 7004    23  21.5    7027
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...