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

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           ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,...

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

4 ответа

Решение

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,...), вы объединяете результат применения функции к различным группам вместе в одном кадре данных (шаг применения и объединения парадигмы "разбить-применить-объединить" в groupby). Таким образом, результатом этого всегда будет снова DataFrame (или Series в зависимости от примененной функции).

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

пример

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

df = df.groupby('l_customer_id_i').agg(lambda x: ','.join(x))
for name in df.index:
    print name
    print df.loc[name]

Цикл по группируемому объекту

Когда вы группируете DataFrame/Series, вы создаетеpandas.core.groupby.generic.DataFrameGroupByобъект, который определяет__iter__()метод, поэтому его можно перебирать, как и любые другие объекты, определяющие этот метод. Его можно преобразовать в список/кортеж/итератор и т. д. На каждой итерации он возвращает кортеж, первый элемент которого является ключом группировщика, а второй элемент — кадром данных, созданным в результате группировки; вы можете думать об этом как об итерацииdict_itemsгде на каждой итерации элементы представляют собой кортежи «ключ-значение». Если вы не выберете столбец или столбцы в объекте groupby, он вернет все столбцы кадра данных. Вывод следующего кода иллюстрирует это.

      import pandas as pd
from IPython.display import display

df = pd.DataFrame({
    'A': ['g1', 'g1', 'g2', 'g1'],
    'B': [1, 2, 3, 4],
    'C': ['a', 'b', 'c', 'd']
})

grouped = df.groupby('A')

list(grouped)         # OK
dict(iter(grouped))   # OK

for x in grouped:
    print(f"    Type of x: {type(x).__name__}\n  Length of x: {len(x)}")
    print(f"Value of x[0]: {x[0]}\n Type of x[1]: {type(x[1]).__name__}")
    display(x[1])

Довольно полезный вариант использования цикла по объекту groupby — разделение кадра данных на отдельные файлы. Например, следующее создает два файла CSV (g_0.csv и g_1.csv) из одного кадра данных.

      for i, (k, g) in enumerate(df.groupby('A')):
    g.to_csv(f"g_{i}.csv")

Цикл по сгруппированному фрейму данных

Как упоминалось выше, объект groupby разбивает кадр данных на кадры данных по ключу. Таким образом, вы можете перебирать каждый сгруппированный фрейм данных, как и любой другой фрейм данных. См. этот ответ , чтобы узнать подробнее о способах перебора кадра данных. Самый эффективный способ, вероятно,itertuples(). Ниже приведен пример создания вложенного словаря с использованием цикла в сгруппированном кадре данных:

      out = {}
for k, g in grouped:            # loop over groupby
    out[k] = {}
    for row in g.itertuples():  # loop over dataframe
        out[k][row.B] = row.C
print(out)
# {'g1': {1: 'a', 2: 'b', 4: 'd'}, 'g2': {3: 'c'}}
Другие вопросы по тегам