В документах показывают , как применить несколько функций на объекте GroupBy в то время , используя Dict с именами вывода столбцов в качестве ключей:
In [563]: grouped['D'].agg({'result1' : np.sum,
.....: 'result2' : np.mean})
.....:
Out[563]:
result2 result1
A
bar -0.579846 -1.739537
foo -0.280588 -1.402938
Однако это работает только для объекта Seriesby. И когда dict аналогично передается в групповой DataFrame, он ожидает, что ключами будут имена столбцов, к которым будет применена функция.
Я хочу применить несколько функций к нескольким столбцам (но некоторые столбцы будут работать несколько раз). Кроме того, некоторые функции будут зависеть от других столбцов в объекте groupby (например, функции sumif). Мое текущее решение состоит в том, чтобы переходить от столбца к столбцу и делать что-то вроде приведенного выше кода, используя лямбда-выражения для функций, которые зависят от других строк. Но это занимает много времени, (я думаю, что это занимает много времени, чтобы перебрать объект groupby). Мне придется изменить это так, чтобы я перебрал весь объект groupby за один проход, но мне интересно, есть ли встроенный способ в пандах, чтобы сделать это несколько чисто.
Например, я пробовал что-то вроде
grouped.agg({'C_sum' : lambda x: x['C'].sum(),
'C_std': lambda x: x['C'].std(),
'D_sum' : lambda x: x['D'].sum()},
'D_sumifC3': lambda x: x['D'][x['C'] == 3].sum(), ...)
но, как и ожидалось, я получаю KeyError (поскольку ключи должны быть столбцом, если agg
вызывается из DataFrame).
Есть ли какой-нибудь встроенный способ сделать то, что я хотел бы сделать, или возможность добавления этой функциональности, или мне просто нужно будет перебирать группу вручную?
Спасибо
Ответы:
Вторая половина принятого в настоящее время ответа устарела и имеет две оценки. Первое и самое важное, вы больше не можете передавать словарь словарей в
agg
метод groupby. Во-вторых, никогда не используйте.ix
.Если вы хотите работать с двумя отдельными столбцами одновременно, я бы предложил использовать
apply
метод, который неявно передает DataFrame в прикладную функцию. Давайте использовать такой же фрейм данных, как приведенный вышеСловарь, отображаемый из имен столбцов в функции агрегации, все еще является отличным способом выполнения агрегации.
Если вам не нравится это уродливое имя лямбда-столбца, вы можете использовать обычную функцию и указать свое имя для специального
__name__
атрибута, например:Использование
apply
и возврат серииТеперь, если у вас было несколько столбцов, которые должны были взаимодействовать друг с другом, вы не можете использовать
agg
, что неявно передает Series в функцию агрегирования. При использованииapply
всей группы в качестве DataFrame передается в функцию.Я рекомендую сделать одну пользовательскую функцию, которая возвращает Серию всех агрегатов. Используйте индекс Series в качестве меток для новых столбцов:
Если вы влюблены в MultiIndexes, вы все равно можете вернуть серию с такой:
источник
a
внутри группы, не0
должно ли это быть0.418500 + 0.446069 = 0.864569
? То же самое относится и к другим ячейкам, цифры не складываются. Может ли быть немного другой базовый фрейм данных использовался в последующих примерах?В первой части вы можете передать слова имен столбцов для ключей и список функций для значений:
ОБНОВЛЕНИЕ 1:
Поскольку агрегатная функция работает в Series, ссылки на другие имена столбцов теряются. Чтобы обойти это, вы можете ссылаться на полный фрейм данных и индексировать его, используя групповые индексы в лямбда-функции.
Вот хакерский обходной путь:
Здесь результирующий столбец «D» состоит из суммированных значений «E».
ОБНОВЛЕНИЕ 2:
Вот метод, который, я думаю, сделает все, что вы попросите. Сначала создайте собственную лямбда-функцию. Ниже дана ссылка на группу. При агрегировании g будет серией. Переход
g.index
кdf.ix[]
выбору текущей группы из DF. Затем я проверяю, является ли столбец C меньше 0,5. Возвращается логическая серия, вg[]
которую выбираются только те строки, которые соответствуют критериям.источник
{funcname: func}
качестве значения вместо списков свои собственные имена. Но в любом случае я не могу передать a,lambda
который использует другие столбцы (какlambda x: x['D'][x['C'] < 3].sum()
выше: "KeyError: 'D'"). Есть идеи, если это возможно?KeyError: 'D'
df['A'].ix[g.index][df['C'] < 0].sum()
. Это начинает становиться довольно грязным - я думаю, что для удобства чтения ручное зацикливание может быть предпочтительным, плюс я не уверен, что есть способ дать ему мое предпочтительное имя вagg
аргументе (вместо<lambda>
). Я буду надеяться, что кто-то может знать более простой способ ...{'D': {'my name':lambda function}}
и он сделает внутренний ключ dict именем столбца.В качестве альтернативы (в основном по эстетике) ответу Теда Петру я обнаружил, что предпочитаю чуть более компактный список. Пожалуйста, не рассматривайте возможность его принятия, это просто более подробный комментарий к ответу Теда плюс код / данные. Python / pandas не мой первый / лучший, но я нашел это, чтобы прочитать хорошо:
Я нахожу это больше напоминающим
dplyr
каналы иdata.table
цепочечные команды. Не сказать, что они лучше, просто мне знакомее. (Я, конечно, признаю силу и для многих предпочтение использовать более формализованныеdef
функции для операций такого типа. Это всего лишь альтернатива, не обязательно лучшая.)Я сгенерировал данные так же, как Тед, я добавлю семя для воспроизводимости.
источник
Pandas >= 0.25.0
названные скопленияНачиная с версии pandas
0.25.0
или выше, мы отходим от словарного агрегирования и переименования и движемся к именованным агрегациям, которые принимают atuple
. Теперь мы можем одновременно агрегировать + переименовывать в более информативное имя столбца:Пример :
Применить
GroupBy.agg
с именованным агрегацией:источник
Новое в версии 0.25.0.
Для поддержки агрегирования по конкретным столбцам с контролем над именами выходных столбцов pandas принимает специальный синтаксис в GroupBy.agg () , известный как «именованная агрегация» , где
pandas.NamedAgg - это просто именованный кортеж. Простые кортежи также допускаются.
Дополнительные ключевые аргументы не передаются в функции агрегации. Только пары (column, aggfunc) должны быть переданы как ** kwargs. Если ваши функции агрегирования требуют дополнительных аргументов, частично примените их с помощью functools.partial ().
Именованная агрегация также действительна для групповой агрегации Series. В этом случае выбор столбца отсутствует, поэтому значения являются только функциями.
источник
Ответ Теда удивителен. Я закончил тем, что использовал уменьшенную версию этого на тот случай, если кому-то будет интересно. Полезно, когда вы ищете одну агрегацию, которая зависит от значений из нескольких столбцов:
создать фрейм данных
группировка и агрегирование с применением (с использованием нескольких столбцов)
группировка и агрегирование с использованием агрегата (с использованием нескольких столбцов)
Мне нравится этот подход, так как я все еще могу использовать агрегат. Возможно, люди дадут мне знать, почему применяется применение для получения нескольких столбцов при агрегировании групп.
Сейчас это кажется очевидным, но до тех пор, пока вы не выберете интересующий столбец сразу после группового , у вас будет доступ ко всем столбцам информационного кадра из функции агрегирования.
доступ только к выбранному столбцу
доступ ко всем столбцам, так как выбор в конце концов волшебство
или аналогично
Надеюсь, это поможет.
источник