2013-08-10 14 views
19

Ho un dizionario Python di feedback utente-item che sembra qualcosa di simile:Pandas frame di dati dal dizionario

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}} 

stavo cercando di convertirlo in un frame di dati panda che sarebbe strutturato come

 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 

Qualsiasi idea sarebbe molto apprezzata :)

risposta

18

Prova seguente codice:

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() 
]) 
+0

Fantastico. Grazie :) – Godel

+1

Grande, ma come opporsi al compito. cioè se dataframe è dato come convertirlo in dizionario. Inoltre, se la colonna viene soffiata a caso. – SujitS

+1

@BlackRabbitt, Utilizzo di default dict 'da collections import defaultdict; d = defaultdict (dict); per utente, articolo, valore in df.values: d.setdefault (utente, {}) [elemento] = valore' – falsetru

0

Si potrebbe provare a farlo in questo modo, forse.

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

Grazie per la risposta rapida. Quando provo questo, ottengo il seguente errore Traceback (chiamata più recente scorso): file "", linea 2, in file "panda \ Core \ frame.py", linea 450, in __init__ rilancio PandasError ('Costruttore DataFrame non correttamente chiamato!') pandas.core.common.PandasError: costruttore DataFrame non correttamente chiamato! – Godel

13

Penso che l'operazione che stai dopo - a UNPIVOT un tavolo - si chiama "fusione". In questo caso, la parte più difficile può essere fatto da pd.melt, e tutto il resto è fondamentalmente ridenominazione e riordino:

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) 

Semplicemente chiamando DataFrame produce qualcosa che ha le informazioni che vogliamo, ma ha la forma sbagliata:

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

Quindi cerchiamo di promuovere l'indice per una colonna reale e migliorare il nome:

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

Quindi possiamo chiamare pd.melt per trasformare le colonne. Se non specifichiamo il nome della variabile che vogliamo, "utente", gli daremo il noioso nome di "variabile" (proprio come assegna al dato stesso il noioso nome "valore").

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

Infine, siamo in grado di riordinare e rinumerare gli indici:

>>> 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 è piuttosto utile una volta che ci si abitua ad esso. Di solito, come qui, si esegue qualche rinominazione/riordino prima e dopo.

+0

Penso che questo dovrebbe anche essere chiamato unpivot ... forse in 0.13! :) –

2

Questo è molto simile alla soluzione melt fornita da DSM:

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

fornisco un'altra possibilità qui utilizzando pd.stack:

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

spiegazioni dettagliate

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 

L'applicazione di stack ruoterà l'asse della colonna su un sottolivello dell'asse di riga già indicizzato da item.Come si vuole user prima, facciamo l'operazione sul dataframe trasposto utilizzando .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 

vi aspettate le colonne di base e non indice, quindi basta resettare l'indice:

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 
Problemi correlati