2015-10-15 13 views
10

Mam słownika słowników w postaci:tworzyć pandy dataframe ze słownika słowników

{'user':{movie:rating} } 

Na przykład

{Jill': {'Avenger: Age of Ultron': 7.0, 
          'Django Unchained': 6.5, 
          'Gone Girl': 9.0, 
          'Kill the Messenger': 8.0} 
'Toby': {'Avenger: Age of Ultron': 8.5, 
           'Django Unchained': 9.0, 
           'Zoolander': 2.0}} 

chcę przekonwertować ten dict z dicts w dataframe pandy z kolumna 1 nazwa użytkownika i inne kolumny oceny filmów, tj.

user Gone_Girl Horrible_Bosses_2 Django_Unchained Zoolander etc. \ 

Howev Niektórzy użytkownicy nie oceniają filmów, więc te filmy nie są uwzględnione w wartościach() dla tego klucza użytkownika(). Byłoby miło w takich przypadkach po prostu wypełnić wpis z NaN.

Jak teraz, I iteracyjne nad klucze, wypełnić listę, a następnie użyć tej listy, aby utworzyć dataframe:

data=[] 
for i,key in enumerate(movie_user_preferences.keys()): 
    try:    
     data.append((key 
        ,movie_user_preferences[key]['Gone Girl'] 
        ,movie_user_preferences[key]['Horrible Bosses 2'] 
        ,movie_user_preferences[key]['Django Unchained'] 
        ,movie_user_preferences[key]['Zoolander'] 
        ,movie_user_preferences[key]['Avenger: Age of Ultron'] 
        ,movie_user_preferences[key]['Kill the Messenger'])) 
    # if no entry, skip 
    except: 
     pass 
df=pd.DataFrame(data=data,columns=['user','Gone_Girl','Horrible_Bosses_2','Django_Unchained','Zoolander','Avenger_Age_of_Ultron','Kill_the_Messenger']) 

Ale to tylko daje mi dataframe użytkowników, którzy ocenili wszystkie filmy w zbiór.

Moim celem jest dołączenie do listy danych poprzez iterację nad etykietami filmów (zamiast powyższego podejścia typu "brute force"), a po drugie, utworzenie ramki danych zawierającej wszystkich użytkowników i umieszczenie wartości pustych w elementach, które mają nie mają ocen filmów.

Odpowiedz

17

Można zdać dict z dict do konstruktora DataFrame:

In [11]: d = {'Jill': {'Django Unchained': 6.5, 'Gone Girl': 9.0, 'Kill the Messenger': 8.0, 'Avenger: Age of Ultron': 7.0}, 'Toby': {'Django Unchained': 9.0, 'Zoolander': 2.0, 'Avenger: Age of Ultron': 8.5}} 

In [12]: pd.DataFrame(d) 
Out[12]: 
         Jill Toby 
Avenger: Age of Ultron 7.0 8.5 
Django Unchained   6.5 9.0 
Gone Girl    9.0 NaN 
Kill the Messenger  8.0 NaN 
Zoolander    NaN 2.0 

Albo użyć metody from_dict:

In [13]: pd.DataFrame.from_dict(d) 
Out[13]: 
         Jill Toby 
Avenger: Age of Ultron 7.0 8.5 
Django Unchained   6.5 9.0 
Gone Girl    9.0 NaN 
Kill the Messenger  8.0 NaN 
Zoolander    NaN 2.0 

In [14]: pd.DataFrame.from_dict(d, orient='index') 
Out[14]: 
     Django Unchained Gone Girl Kill the Messenger Avenger: Age of Ultron Zoolander 
Jill    6.5   9     8      7.0  NaN 
Toby    9.0  NaN     NaN      8.5   2 
+0

Czy istnieje sposób na zmianę nazwy użytkownika na pojedynczą kolumnę zamiast indeksu? – Feynman27

+3

pd.DataFrame.from_dict (d, orient = 'index'). Reset_index() –

+0

Świetnie. Dziękuję Ci! – Feynman27

0

Takie podejście brute-force również wydaje się działać, ale iteracji nad Etykiety filmowe nadal będą moim zdaniem bardziej wytrzymałe.

data=[] 
for i,key in enumerate(movie_user_preferences.keys()): 
    try:    
     data.append((key 
        ,movie_user_preferences[key]['Gone Girl'] if 'Gone Girl' in movie_user_preferences[key] else 'NaN' 
        ,movie_user_preferences[key]['Horrible Bosses 2'] if 'Horrible Bosses 2' in movie_user_preferences[key] else 'NaN' 
        ,movie_user_preferences[key]['Django Unchained'] if 'Django Unchained' in movie_user_preferences[key] else 'NaN' 
        ,movie_user_preferences[key]['Zoolander'] if 'Zoolander' in movie_user_preferences[key] else 'NaN' 
        ,movie_user_preferences[key]['Avenger: Age of Ultron'] if 'Avenger: Age of Ultron' in movie_user_preferences[key] else 'NaN' 
        ,movie_user_preferences[key]['Kill the Messenger'] if 'Kill the Messenger' in movie_user_preferences[key] else 'NaN')) 

    # if no entry, skip 
    except: 
     pass 


user Gone_Girl Horrible_Bosses_2 Django_Unchained Zoolander \ 
0  Sam   6     3    7.5   7 
1  Max  10     6    7.0  10 
2 Robert  NaN     5    7.0   9 
3  Toby  NaN    NaN    9.0   2 
4 Julia  6.5    NaN    6.0  6.5 
5 William   7     4    8.0   4 
6  Jill   9    NaN    6.5  NaN 

Avenger_Age_of_Ultron Kill_the_Messenger 
0     10.0    5.5 
1     7.0     5 
2     8.0     9 
3     8.5    NaN 
4     10.0     6 
5     6.0    6.5 
6     7.0     8