Именование возвращенных столбцов в функции агрегации Pandas?

У меня проблемы с функциональностью группы Панд. Я прочитал документацию , но не могу понять, как применять агрегированные функции к нескольким столбцам и иметь собственные имена для этих столбцов.

Это очень близко, но возвращаемая структура данных имеет вложенные заголовки столбцов:

data.groupby("Country").agg( {"column1": {"foo": sum()}, "column2": {"mean": np.mean, "std": np.std}}) 

(т. е. хочу взять среднее значение и std столбца2, но вернуть эти столбцы как «mean» и «std»)

Что мне не хватает?

    Это приведет к потере внешнего уровня из индекса иерархической колонки:

     df = data.groupby(...).agg(...) df.columns = df.columns.droplevel(0) 

    Если вы хотите сохранить внешний уровень, вы можете использовать функцию ravel () в многоуровневом столбце для создания новых меток:

     df.columns = ["_".join(x) for x in df.columns.ravel()] 

    Например:

     import pandas as pd import pandas.rpy.common as com import numpy as np data = com.load_data('Loblolly') print(data.head()) # height age Seed # 1 4.51 3 301 # 15 10.89 5 301 # 29 28.72 10 301 # 43 41.74 15 301 # 57 52.70 20 301 df = data.groupby('Seed').agg( {'age':['sum'], 'height':['mean', 'std']}) print(df.head()) # age height # sum std mean # Seed # 301 78 22.638417 33.246667 # 303 78 23.499706 34.106667 # 305 78 23.927090 35.115000 # 307 78 22.222266 31.328333 # 309 78 23.132574 33.781667 df.columns = df.columns.droplevel(0) print(df.head()) 

    доходность

      sum std mean Seed 301 78 22.638417 33.246667 303 78 23.499706 34.106667 305 78 23.927090 35.115000 307 78 22.222266 31.328333 309 78 23.132574 33.781667 

    В качестве альтернативы, чтобы сохранить первый уровень индекса:

     df = data.groupby('Seed').agg( {'age':['sum'], 'height':['mean', 'std']}) df.columns = ["_".join(x) for x in df.columns.ravel()] 

    доходность

      age_sum height_std height_mean Seed 301 78 22.638417 33.246667 303 78 23.499706 34.106667 305 78 23.927090 35.115000 307 78 22.222266 31.328333 309 78 23.132574 33.781667 

    В настоящее время принятый ответ unutbu описывает отличный способ сделать это в версиях pandas <= 0.20. Однако, начиная с pandas 0.20, этот метод вызывает предупреждение о том, что синтаксис не будет доступен в будущих версиях панд.

    Серии:

    FutureWarning: использование dict для серии для агрегации устарело и будет удалено в будущей версии

    DataFrames:

    FutureWarning: использование dict с переименованием устарело и будет удалено в будущей версии

    Согласно pandas 0.20 changelog , рекомендуемый способ переименования столбцов при агрегировании выглядит следующим образом.

     # Create a sample data frame df = pd.DataFrame({'A': [1, 1, 1, 2, 2], 'B': range(5), 'C': range(5)}) # ==== SINGLE COLUMN (SERIES) ==== # Syntax soon to be deprecated df.groupby('A').B.agg({'foo': 'count'}) # Recommended replacement syntax df.groupby('A').B.agg(['count']).rename(columns={'count': 'foo'}) # ==== MULTI COLUMN ==== # Syntax soon to be deprecated df.groupby('A').agg({'B': {'foo': 'sum'}, 'C': {'bar': 'min'}}) # Recommended replacement syntax df.groupby('A').agg({'B': 'sum', 'C': 'min'}).rename(columns={'B': 'foo', 'C': 'bar'}) # As the recommended syntax is more verbose, parentheses can # be used to introduce line breaks and increase readability (df.groupby('A') .agg({'B': 'sum', 'C': 'min'}) .rename(columns={'B': 'foo', 'C': 'bar'}) ) 

    Для получения дополнительной информации см. Журнал изменений 0.20 .


    Обновление 2017-01-03 в ответ на комментарий @ JunkMechanic.

    С синтаксисом словарного стиля старого стиля было возможно передать несколько lambda функций на .agg , так как они были бы переименованы с ключом в переданном словаре:

     >>> df.groupby('A').agg({'B': {'min': lambda x: x.min(), 'max': lambda x: x.max()}}) B max min A 1 2 0 2 4 3 

    Несколько функций также могут быть переданы в один столбец в виде списка:

     >>> df.groupby('A').agg({'B': [np.min, np.max]}) B amin amax A 1 0 2 2 3 4 

    Однако это не работает с лямбда-функциями, поскольку они анонимны и все возвращают <lambda> , что вызывает столкновение имен:

     >>> df.groupby('A').agg({'B': [lambda x: x.min(), lambda x: x.max]}) SpecificationError: Function names must be unique, found multiple named <lambda> 

    Чтобы избежать SpecificationError , именованные функции могут быть определены априорно вместо использования lambda . Соответствующие имена функций также не позволяют вызывать .rename в кадре данных впоследствии. Эти функции могут быть переданы с таким же синтаксисом списка, как указано выше:

     >>> def my_min(x): >>> return x.min() >>> def my_max(x): >>> return x.max() >>> df.groupby('A').agg({'B': [my_min, my_max]}) B my_min my_max A 1 0 2 2 3 4 

    Если вы хотите иметь поведение, подобное JMP, создавая заголовки столбцов, которые содержат всю информацию из мультииндекса, который вы можете использовать:

     newidx = [] for (n1,n2) in df.columns.ravel(): newidx.append("%s-%s" % (n1,n2)) df.columns=newidx 

    Он изменит ваш фреймворк с:

      IV mean std first V 4200.0 25.499536 31.557133 4200.0 4300.0 25.605662 31.678046 4300.0 4400.0 26.679005 32.919996 4400.0 4500.0 26.786458 32.811633 4500.0 

    в

      I-mean I-std V-first V 4200.0 25.499536 31.557133 4200.0 4300.0 25.605662 31.678046 4300.0 4400.0 26.679005 32.919996 4400.0 4500.0 26.786458 32.811633 4500.0