Как перебрать сгруппированный фрейм данных Pandas?

165

DataFrame:

  c_os_family_ss c_os_major_is l_customer_id_i
0      Windows 7                         90418
1      Windows 7                         90418
2      Windows 7                         90418

Код:

print df
for name, group in df.groupby('l_customer_id_i').agg(lambda x: ','.join(x)):
    print name
    print group

Я пытаюсь перебрать агрегированные данные, но получаю сообщение об ошибке:

ValueError: слишком много значений для распаковки

@EdChum, вот ожидаемый результат:

                                                    c_os_family_ss  \
l_customer_id_i
131572           Windows 7,Windows 7,Windows 7,Windows 7,Window...
135467           Windows 7,Windows 7,Windows 7,Windows 7,Window...

                                                     c_os_major_is
l_customer_id_i
131572           ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,...
135467           ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,...

Проблема не в выводе, я хочу перебрать каждую группу.

Tjorriemorrie
источник

Ответы:

246

df.groupby('l_customer_id_i').agg(lambda x: ','.join(x)) уже возвращает фрейм данных, поэтому вы больше не можете перебирать группы.

В общем:

  • df.groupby(...)возвращает GroupByобъект (DataFrameGroupBy или SeriesGroupBy), и с его помощью вы можете выполнять итерацию по группам (как описано в документации здесь ). Вы можете сделать что-то вроде:

    grouped = df.groupby('A')
    
    for name, group in grouped:
        ...
    
  • При применении функции на GroupBy, в вашем примере df.groupby(...).agg(...)(но это также может быть transform, apply, mean, ...), вы скомбинировать результат применения функции к различным группам в одном dataframe (Применить и объединить шаг из парадигма groupby «разделить-применить-объединить»). Таким образом, результатом этого всегда будет DataFrame (или серия в зависимости от применяемой функции).

Йорис
источник
59

Вот пример итерации pd.DataFrameпо столбцу atable. В качестве примера использования внутри forцикла генерируются операторы create для базы данных SQL :

import pandas as pd

df1 = pd.DataFrame({
    'atable':     ['Users', 'Users', 'Domains', 'Domains', 'Locks'],
    'column':     ['col_1', 'col_2', 'col_a', 'col_b', 'col'],
    'column_type':['varchar', 'varchar', 'int', 'varchar', 'varchar'],
    'is_null':    ['No', 'No', 'Yes', 'No', 'Yes'],
})

df1_grouped = df1.groupby('atable')

# iterate over each group
for group_name, df_group in df1_grouped:
    print('\nCREATE TABLE {}('.format(group_name))

    for row_index, row in df_group.iterrows():
        col = row['column']
        column_type = row['column_type']
        is_null = 'NOT NULL' if row['is_null'] == 'NO' else ''
        print('\t{} {} {},'.format(col, column_type, is_null))

    print(");")
Андрей Сура
источник
9
Спасибо за демонстрацию того, что вы можете выполнять итерацию по отдельному groupпользователю for row, data in group.iterrows()!
tatlar
18

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

df = df.groupby('l_customer_id_i').agg(lambda x: ','.join(x))
for name in df.index:
    print name
    print df.loc[name]
хинер
источник