Создание pandas данных из словаря словарей

У меня есть словарь словарей формы:

{'user':{movie:rating} }

Например,

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

Я хочу преобразовать этот dict dicts в фреймворк pandas со столбцом 1 имя пользователя и другие столбцы рейтинги фильмов i.e.

user  Gone_Girl  Horrible_Bosses_2  Django_Unchained  Zoolander etc. \

Однако некоторые пользователи не оценивали фильмы и поэтому эти фильмы не включены в значения() для этого пользовательского ключа(). Было бы неплохо в этих случаях просто заполнить запись NaN.

На данный момент я перебираю ключи, заполняю список, а затем использую этот список для создания фрейма данных:

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'])

Но это только дает мне фреймворк пользователей, которые оценили все фильмы в наборе.

Моя цель - добавить в список данных итерацию над метками фильма (вместо приведенного выше подхода к грубой силе) и, во-вторых, создать фрейм данных, который включает всех пользователей, и который помещает нулевые значения в элементы, которые не есть рейтинги фильмов.

Ответ 1

Вы можете передать dict dict в конструктор 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

Или используйте метод 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

Ответ 2

Этот подход с грубой силой также работает, но повторение над лейблами фильмов по-прежнему будет более надежным.

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