Панды суммируются по группам, но исключают определенные столбцы

88

Каков наилучший способ сделать groupby в кадре данных Pandas, но исключить некоторые столбцы из этой groupby? например, у меня есть следующий фрейм данных:

Code   Country      Item_Code   Item    Ele_Code    Unit    Y1961    Y1962   Y1963
2      Afghanistan  15          Wheat   5312        Ha      10       20      30
2      Afghanistan  25          Maize   5312        Ha      10       20      30
4      Angola       15          Wheat   7312        Ha      30       40      50
4      Angola       25          Maize   7312        Ha      30       40      50

Я хочу сгруппировать по столбцам Country и Item_Code и вычислить только сумму строк, попадающих под столбцы Y1961, Y1962 и Y1963. Результирующий фрейм данных должен выглядеть так:

Code   Country      Item_Code   Item    Ele_Code    Unit    Y1961    Y1962   Y1963
2      Afghanistan  15          C3      5312        Ha      20       40       60
4      Angola       25          C4      7312        Ha      60       80      100

Прямо сейчас делаю вот что:

df.groupby('Country').sum()

Однако при этом также складываются значения в столбце Item_Code. Есть ли способ указать, какие столбцы включить в sum()операцию, а какие исключить?

user308827
источник

Ответы:

117

Вы можете выбрать столбцы в группе:

In [11]: df.groupby(['Country', 'Item_Code'])[["Y1961", "Y1962", "Y1963"]].sum()
Out[11]:
                       Y1961  Y1962  Y1963
Country     Item_Code
Afghanistan 15            10     20     30
            25            10     20     30
Angola      15            30     40     50
            25            30     40     50

Обратите внимание, что переданный список должен быть подмножеством столбцов, иначе вы увидите KeyError.

Энди Хайден
источник
1
Как включить количество записей для каждой страны и кода товара в другой столбец?
Sushant Kulkarni
Вы можете создать фиктивный столбец перед группировкой, который содержит только 1., тогда сумма суммирует их, создавая счетчик.
Мэтт У.
Если вы просто хотите исключить один или два столбца, вы получаете все имена столбцов, как в, listColumns = list(df.columns)затем вы удаляете столбцы, которые вам не нужны, listColumns.remove('Y1964')и, наконец, проводите суммирование:df.groupby(['Country', 'Item_Code'])[listColumns].sum()
Роберто Стеллинг,
Большое спасибо. Я могу заставить работать группу, но не часть выбора. Список столбцов, которые я ввел, находится среди фрейма данных, но он продолжает вызывать ValueError:cannot reindex from a duplicate axis
Боуэн Лю
@BowenLiu, если у вас есть несколько столбцов с одинаковым именем, он покажет эту ошибку. В этом случае вам придется использовать iloc to или loc, чтобы получить нужные столбцы, я думаю, вам придется сделать это до groupby.
Энди Хайден
40

aggФункция сделает это для вас. Передайте столбцы и функцию как dict с столбцом, выведите:

df.groupby(['Country', 'Item_Code']).agg({'Y1961': np.sum, 'Y1962': [np.sum, np.mean]})  # Added example for two output columns from a single input column

Это отобразит только группу по столбцам и указанные столбцы агрегирования. В этом примере я включил две функции аггирования, примененные к «Y1962».

Чтобы получить именно то, что вы надеялись увидеть, включите другие столбцы в группу по и примените суммы к переменным Y в кадре:

df.groupby(['Code', 'Country', 'Item_Code', 'Item', 'Ele_Code', 'Unit']).agg({'Y1961': np.sum, 'Y1962': np.sum, 'Y1963': np.sum})
leroyJr
источник
1
спасибо, это можно обобщить? У меня много столбцов формы Y1961 ... поэтому я создаю список вроде этого: yrs = ['Y' + str (x) for x in range (1961, 2010 + 1, 1)]. Может ли ваше решение использовать "yrs" внутри agg?
user308827
Мне очень нравится эта идея. Уловка состоит в том, чтобы построить этот dict со значением, являющимся функцией numpy sum. И наоборот, если все, что вы хотите сделать, это просуммировать все оставшиеся столбцы, ваше исходное решение будет работать, если все столбцы group by включены в оператор group by.
leroyJr
11

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

columns = ['Y'+str(i) for year in range(1967, 2011)]

df.groupby('Country')[columns].agg('sum')
Супер звезда
источник