¿Cómo recorrer el marco de datos de Pandas agrupado?

146

Marco de datos:

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

Código:

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

Estoy tratando de recorrer los datos agregados, pero aparece el error:

ValueError: demasiados valores para descomprimir

@EdChum, aquí está el resultado esperado:

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

La salida no es el problema, deseo recorrer cada grupo.

Tjorriemorrie
fuente

Respuestas:

224

df.groupby('l_customer_id_i').agg(lambda x: ','.join(x)) ya devuelve un marco de datos, por lo que ya no puede recorrer los grupos.

En general:

  • df.groupby(...)devuelve un GroupByobjeto (un DataFrameGroupBy o SeriesGroupBy), y con esto, puede iterar a través de los grupos (como se explica en los documentos aquí ). Puedes hacer algo como:

    grouped = df.groupby('A')
    
    for name, group in grouped:
        ...
    
  • Cuando se aplica una función en la GroupBy, en su ejemplo df.groupby(...).agg(...)(pero esto también puede ser transform, apply, mean, ...), que combina el resultado de aplicar la función de los diferentes grupos juntos en una trama de datos (la aplican y combinan paso del paradigma 'split-apply-combine' de groupby). Entonces, el resultado de esto siempre será nuevamente un DataFrame (o una Serie dependiendo de la función aplicada).

joris
fuente
50

Aquí hay un ejemplo de iteración sobre una pd.DataFrameagrupada por la columna atable. Para un caso de uso de muestra, las declaraciones "crear" para una base de datos SQL se generan dentro del forbucle:

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(");")
Andrei Sura
fuente
8
¡Gracias por demostrar que puede iterar a través de un individuo groupusando for row, data in group.iterrows()!
tatlar
16

Puede iterar sobre los valores del índice si su marco de datos ya se ha creado.

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