Я хочу задокументировать конкретный случай использования метода '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
Теперь мы продолжим работу с групповыми операциями и вычисление новогоРезультаты:
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
предупреждением):
Интересно, что второй метод немного быстрее, время (1,66 мс, 1,69 мс, 1,73 мс).
У меня есть вопрос, есть липроще?И как это сделать для DataFrame с мультииндексом строки?