Marco de datos de pandas del diccionario

Tengo un diccionario de Python de calificaciones de elementos de usuario que se parece a esto:

sample={'user1': {'item1': 2.5, 'item2': 3.5, 'item3': 3.0, 'item4': 3.5, 'item5': 2.5, 'item6': 3.0}, 'user2': {'item1': 2.5, 'item2': 3.0, 'item3': 3.5, 'item4': 4.0}, 'user3': {'item2':4.5,'item5':1.0,'item6':4.0}} 

Estaba buscando convertirlo en un dataframe pandas que sería estructurado como

  col1 col2 col3 0 user1 item1 2.5 1 user1 item2 3.5 2 user1 item3 3.0 3 user1 item4 3.5 4 user1 item5 2.5 5 user1 item6 3.0 6 user2 item1 2.5 7 user2 item2 3.0 8 user2 item3 3.5 9 user2 item4 4.0 10 user3 item2 4.5 11 user3 item5 1.0 12 user3 item6 4.0 

Cualquier idea será altamente apreciada 🙂

Intente el siguiente código:

 import pandas sample={'user1': {'item1': 2.5, 'item2': 3.5, 'item3': 3.0, 'item4': 3.5, 'item5': 2.5, 'item6': 3.0}, 'user2': {'item1': 2.5, 'item2': 3.0, 'item3': 3.5, 'item4': 4.0}, 'user3': {'item2':4.5,'item5':1.0,'item6':4.0}} df = pandas.DataFrame([ [col1,col2,col3] for col1, d in sample.items() for col2, col3 in d.items() ]) 

Creo que la operación que estás buscando, para no dividir una tabla, se llama “fusión”. En este caso, la parte difícil puede ser realizada por pd.melt , y todo lo demás es básicamente cambiar el nombre y reordenar:

 df = pd.DataFrame(sample).reset_index().rename(columns={"index": "item"}) df = pd.melt(df, "item", var_name="user").dropna() df = df[["user", "item", "value"]].reset_index(drop=True) 

Simplemente llamar a DataFrame produce algo que tiene la información que queremos pero que tiene la forma incorrecta:

 >>> df = pd.DataFrame(sample) >>> df user1 user2 user3 item1 2.5 2.5 NaN item2 3.5 3.0 4.5 item3 3.0 3.5 NaN item4 3.5 4.0 NaN item5 2.5 NaN 1.0 item6 3.0 NaN 4.0 

Así que vamos a promover el índice a una columna real y mejorar el nombre:

 >>> df = pd.DataFrame(sample).reset_index().rename(columns={"index": "item"}) >>> df item user1 user2 user3 0 item1 2.5 2.5 NaN 1 item2 3.5 3.0 4.5 2 item3 3.0 3.5 NaN 3 item4 3.5 4.0 NaN 4 item5 2.5 NaN 1.0 5 item6 3.0 NaN 4.0 

Luego podemos llamar a pd.melt para convertir las columnas. Si no especificamos el nombre de la variable que queremos, “usuario”, le daremos el nombre aburrido de “variable” (al igual que le da a los datos el nombre aburrido “valor”).

 >>> df = pd.melt(df, "item", var_name="user").dropna() >>> df item user value 0 item1 user1 2.5 1 item2 user1 3.5 2 item3 user1 3.0 3 item4 user1 3.5 4 item5 user1 2.5 5 item6 user1 3.0 6 item1 user2 2.5 7 item2 user2 3.0 8 item3 user2 3.5 9 item4 user2 4.0 13 item2 user3 4.5 16 item5 user3 1.0 17 item6 user3 4.0 

Finalmente, podemos reordenar y renumerar los índices:

 >>> df = df[["user", "item", "value"]].reset_index(drop=True) >>> df user item value 0 user1 item1 2.5 1 user1 item2 3.5 2 user1 item3 3.0 3 user1 item4 3.5 4 user1 item5 2.5 5 user1 item6 3.0 6 user2 item1 2.5 7 user2 item2 3.0 8 user2 item3 3.5 9 user2 item4 4.0 10 user3 item2 4.5 11 user3 item5 1.0 12 user3 item6 4.0 

melt es bastante útil una vez que te acostumbras. Por lo general, como aquí, se hace un cambio de nombre / ordenamiento antes y después.

Proporciono otra posibilidad aquí usando pd.stack :

 df = pd.DataFrame(sample) df = df.T.stack().reset_index() 

Explicaciones detalladas

 In [24]: df = pd.DataFrame(sample) In [25]: df Out[25]: user1 user2 user3 item1 2.5 2.5 NaN item2 3.5 3.0 4.5 item3 3.0 3.5 NaN item4 3.5 4.0 NaN item5 2.5 NaN 1.0 item6 3.0 NaN 4.0 

La aplicación de stack girará el eje de columna en un subnivel del eje de fila ya indexado por item . Como primero desea el user , hagamos la operación en el DataFrame transpuesto utilizando .T :

 In [34]: df = df.T.stack() In [35]: df Out[35]: user1 item1 2.5 item2 3.5 item3 3.0 item4 3.5 item5 2.5 item6 3.0 user2 item1 2.5 item2 3.0 item3 3.5 item4 4.0 user3 item2 4.5 item5 1.0 item6 4.0 dtype: float64 

Espera columnas básicas y no índice, así que simplemente reinicie el índice:

 In [36]: df = df.reset_index() In [37]: df Out[37]: level_0 level_1 0 0 user1 item1 2.5 1 user1 item2 3.5 2 user1 item3 3.0 3 user1 item4 3.5 4 user1 item5 2.5 5 user1 item6 3.0 6 user2 item1 2.5 7 user2 item2 3.0 8 user2 item3 3.5 9 user2 item4 4.0 10 user3 item2 4.5 11 user3 item5 1.0 12 user3 item6 4.0 

Este es muy similar a la solución de melt proporcionada por DSM:

 df = DataFrame(sample) df = df.unstack().dropna().reset_index() df = df.rename(columns={'level_0':'col1', 'level_1':'col2', 0:'col3'}) 

Podrías intentar hacerlo así tal vez.

 temp=[] for item in sample: temp.append(pandas.DataFrame(item)) self.results = pandas.concat(temp)