Convertir un objeto Pandas GroupBy a DataFrame

Estoy empezando con datos de entrada como este

df1 = pandas.DataFrame( { "Name" : ["Alice", "Bob", "Mallory", "Mallory", "Bob" , "Mallory"] , "City" : ["Seattle", "Seattle", "Portland", "Seattle", "Seattle", "Portland"] } ) 

Que cuando se imprime aparece así:

  City Name 0 Seattle Alice 1 Seattle Bob 2 Portland Mallory 3 Seattle Mallory 4 Seattle Bob 5 Portland Mallory 

La agrupación es bastante simple:

 g1 = df1.groupby( [ "Name", "City"] ).count() 

y la impresión produce un objeto GroupBy :

  City Name Name City Alice Seattle 1 1 Bob Seattle 2 2 Mallory Portland 2 2 Seattle 1 1 

Pero lo que quiero eventualmente es otro objeto DataFrame que contenga todas las filas en el objeto GroupBy. En otras palabras quiero obtener el siguiente resultado:

  City Name Name City Alice Seattle 1 1 Bob Seattle 2 2 Mallory Portland 2 2 Mallory Seattle 1 1 

No puedo ver cómo lograr esto en la documentación de los pandas. Cualquier consejo sería bienvenido.

g1 aquí hay un DataFrame. Sin embargo, tiene un índice jerárquico:

 In [19]: type(g1) Out[19]: pandas.core.frame.DataFrame In [20]: g1.index Out[20]: MultiIndex([('Alice', 'Seattle'), ('Bob', 'Seattle'), ('Mallory', 'Portland'), ('Mallory', 'Seattle')], dtype=object) 

Tal vez quieres algo como esto?

 In [21]: g1.add_suffix('_Count').reset_index() Out[21]: Name City City_Count Name_Count 0 Alice Seattle 1 1 1 Bob Seattle 2 2 2 Mallory Portland 2 2 3 Mallory Seattle 1 1 

O algo como:

 In [36]: DataFrame({'count' : df1.groupby( [ "Name", "City"] ).size()}).reset_index() Out[36]: Name City count 0 Alice Seattle 1 1 Bob Seattle 2 2 Mallory Portland 2 3 Mallory Seattle 1 

Quiero cambiar ligeramente la respuesta dada por Wes, porque la versión 0.16.2 requiere as_index=False . Si no lo configura, obtiene un dataframe vacío.

Fuente :

Las funciones de agregación no devolverán los grupos que está agregando si se denominan columnas, cuando as_index=True , el valor predeterminado. Las columnas agrupadas serán los índices del objeto devuelto.

Al pasar as_index=False se devolverán los grupos que está agregando, si se denominan columnas.

Las funciones de agregación son aquellas que reducen la dimensión de los objetos devueltos, por ejemplo: mean , sum , size , count , std , var , sem , describe , first , last , nth , min , max . Esto es lo que sucede cuando haces, por ejemplo, DataFrame.sum() y recuperas una Series .

Puede actuar como un reductor o un filtro, consulte aquí .

 import pandas as pd df1 = pd.DataFrame({"Name":["Alice", "Bob", "Mallory", "Mallory", "Bob" , "Mallory"], "City":["Seattle","Seattle","Portland","Seattle","Seattle","Portland"]}) print df1 # # City Name #0 Seattle Alice #1 Seattle Bob #2 Portland Mallory #3 Seattle Mallory #4 Seattle Bob #5 Portland Mallory # g1 = df1.groupby(["Name", "City"], as_index=False).count() print g1 # # City Name #Name City #Alice Seattle 1 1 #Bob Seattle 2 2 #Mallory Portland 2 2 # Seattle 1 1 # 

EDITAR:

En la versión 0.17.1 y posterior, puede usar un subset en count y reset_index con el name parámetro en size :

 print df1.groupby(["Name", "City"], as_index=False ).count() #IndexError: list index out of range print df1.groupby(["Name", "City"]).count() #Empty DataFrame #Columns: [] #Index: [(Alice, Seattle), (Bob, Seattle), (Mallory, Portland), (Mallory, Seattle)] print df1.groupby(["Name", "City"])[['Name','City']].count() # Name City #Name City #Alice Seattle 1 1 #Bob Seattle 2 2 #Mallory Portland 2 2 # Seattle 1 1 print df1.groupby(["Name", "City"]).size().reset_index(name='count') # Name City count #0 Alice Seattle 1 #1 Bob Seattle 2 #2 Mallory Portland 2 #3 Mallory Seattle 1 

La diferencia entre count y size es que el size cuenta los valores de NaN, mientras que el count no.

Simplemente, esto debería hacer la tarea:

 import pandas as pd grouped_df = df1.groupby( [ "Name", "City"] ) pd.DataFrame(grouped_df.size().reset_index(name = "Group_Count")) 

Aquí, grouped_df.size () extrae el recuento único de groupby, y el método reset_index () restablece el nombre de la columna que desea que sea. Finalmente, se llama a la función Pandas Dataframe () para crear el objeto DataFrame.

Tal vez entiendo mal la pregunta, pero si desea convertir el grupo de nuevo a un dataframe, puede usar .to_frame (). Quería restablecer el índice cuando hice esto, así que también incluí esa parte.

código de ejemplo no relacionado con la pregunta

 df = df['TIME'].groupby(df['Name']).min() df = df.to_frame() df = df.reset_index(level=['Name',"TIME"]) 

Encontré que esto funcionó para mí.

 import numpy as np import pandas as pd df1 = pd.DataFrame({ "Name" : ["Alice", "Bob", "Mallory", "Mallory", "Bob" , "Mallory"] , "City" : ["Seattle", "Seattle", "Portland", "Seattle", "Seattle", "Portland"]}) df1['City_count'] = 1 df1['Name_count'] = 1 df1.groupby(['Name', 'City'], as_index=False).count() 

He agregado con datos en cantidad y almacene a dataframe

 almo_grp_data = pd.DataFrame({'Qty_cnt' : almo_slt_models_data.groupby( ['orderDate','Item','State Abv'] )['Qty'].sum()}).reset_index() 

Abajo la solución puede ser más simple:

 df1.reset_index().groupby( [ "Name", "City"],as_index=False ).count() 

Estas soluciones solo funcionaron parcialmente para mí porque estaba haciendo agregaciones múltiples. Aquí hay una salida de muestra de mi agrupada por la que quería convertir a un dataframe:

Salida Groupby

Como quería más que el recuento proporcionado por reset_index (), escribí un método manual para convertir la imagen de arriba en un dataframe. Entiendo que esta no es la forma más python / pandas de hacer esto, ya que es bastante detallada y explícita, pero era todo lo que necesitaba. Básicamente, use el método reset_index () explicado anteriormente para iniciar un dataframe de “andamiaje”, luego recorra los emparejamientos de grupos en el dataframe agrupado, recupere los índices, realice sus cálculos contra el dataframe no agrupado y establezca el valor en su nuevo dataframe agregado .

 df_grouped = df[['Salary Basis', 'Job Title', 'Hourly Rate', 'Male Count', 'Female Count']] df_grouped = df_grouped.groupby(['Salary Basis', 'Job Title'], as_index=False) # Grouped gives us the indices we want for each grouping # We cannot convert a groupedby object back to a dataframe, so we need to do it manually # Create a new dataframe to work against df_aggregated = df_grouped.size().to_frame('Total Count').reset_index() df_aggregated['Male Count'] = 0 df_aggregated['Female Count'] = 0 df_aggregated['Job Rate'] = 0 def manualAggregations(indices_array): temp_df = df.iloc[indices_array] return { 'Male Count': temp_df['Male Count'].sum(), 'Female Count': temp_df['Female Count'].sum(), 'Job Rate': temp_df['Hourly Rate'].max() } for name, group in df_grouped: ix = df_grouped.indices[name] calcDict = manualAggregations(ix) for key in calcDict: #Salary Basis, Job Title columns = list(name) df_aggregated.loc[(df_aggregated['Salary Basis'] == columns[0]) & (df_aggregated['Job Title'] == columns[1]), key] = calcDict[key] 

Si un diccionario no es lo tuyo, los cálculos podrían aplicarse en línea en el bucle for:

  df_aggregated['Male Count'].loc[(df_aggregated['Salary Basis'] == columns[0]) & (df_aggregated['Job Title'] == columns[1])] = df['Male Count'].iloc[ix].sum() 

La clave es usar el método reset_index () .

Utilizar:

 import pandas df1 = pandas.DataFrame( { "Name" : ["Alice", "Bob", "Mallory", "Mallory", "Bob" , "Mallory"] , "City" : ["Seattle", "Seattle", "Portland", "Seattle", "Seattle", "Portland"] } ) g1 = df1.groupby( [ "Name", "City"] ).count().reset_index() 

Ahora tienes tu nuevo dataframe en g1 :

marco de datos de resultados