从列中分解dict

2024-03-29 07:50:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下建议:

    movie_id    rating_all 
0   tt7653254   [{'age': 'all', 'avg_rating': 8.1, 'count': 109326}, {'age': '<18', 'avg_rating': 8.8, 'count': 318}, {'age': '18-29', 'avg_rating': 8.3, 'count': 29740}, {'age': '30-44', 'avg_rating': 8.0, 'count': 33012}, {'age': '45+', 'avg_rating': 7.7, 'count': 7875}]
1   tt8579674   [{'age': 'all', 'avg_rating': 8.6, 'count': 9420}, {'age': '<18', 'avg_rating': 9.1, 'count': 35}, {'age': '18-29', 'avg_rating': 8.7, 'count': 2437}, {'age': '30-44', 'avg_rating': 8.5, 'count': 2529}, {'age': '45+', 'avg_rating': 8.3, 'count': 960}]
2   tt7286456   [{'age': 'all', 'avg_rating': 8.6, 'count': 592441}, {'age': '<18', 'avg_rating': 9.1, 'count': 2244}, {'age': '18-29', 'avg_rating': 8.7, 'count': 160506}, {'age': '30-44', 'avg_rating': 8.5, 'count': 160158}, {'age': '45+', 'avg_rating': 8.3, 'count': 30451}]
3   tt1302006   [{'age': 'all', 'avg_rating': 8.1, 'count': 187675}, {'age': '<18', 'avg_rating': 8.7, 'count': 461}, {'age': '18-29', 'avg_rating': 8.3, 'count': 41951}, {'age': '30-44', 'avg_rating': 7.9, 'count': 59729}, {'age': '45+', 'avg_rating': 7.8, 'count': 18550}]
4   tt7131622   [{'age': 'all', 'avg_rating': 7.8, 'count': 323152}, {'age': '<18', 'avg_rating': 8.4, 'count': 955}, {'age': '18-29', 'avg_rating': 7.9, 'count': 82133}, {'age': '30-44', 'avg_rating': 7.6, 'count': 95878}, {'age': '45+', 'avg_rating': 7.5, 'count': 26383}]
5   tt8637428   [{'age': 'all', 'avg_rating': 7.7, 'count': 21362}, {'age': '<18', 'avg_rating': 8.0, 'count': 45}, {'age': '18-29', 'avg_rating': 7.9, 'count': 5901}, {'age': '30-44', 'avg_rating': 7.6, 'count': 6492}, {'age': '45+', 'avg_rating': 7.3, 'count': 2133}]

我想把它转换成:

    movie_id    all_avg     all_count   <18_avg     <18_count   18-29_avg
0   tt7653254   8.1         109326      8.8         318         8.3
1   tt8579674   8.6         9420        9.1         35          8.7
2   tt7286456   8.6         592441      9.1         2244        8.7
3   tt1302006   8.1         187675      8.7         461         8.3
4   tt7131622   7.8         323152      8.4         955         7.9
5   tt8637428   7.7         21362       8           45          7.9

等等

我试过了

ratings.set_index('movie_id')['rating_all'].apply(pd.Series).reset_index()

和使用

json_normalize(data, 
               record_path=['rating_all'], 
               meta=['movie_id']).set_index('movie_id')

但没有人给出类似的东西。有没有一种简单的方法可以将字典分解成列


Tags: idageindexcountallmovieavgrating
1条回答
网友
1楼 · 发布于 2024-03-29 07:50:16

假设我正确地解释了您要做的事情,您可以按如下方式实现:

从(我假设的!!)开始是您的输入数据集:

    movie_id                                            ratings
0  tt7653254  [{'age': 'all', 'avg_rating': 8.1, 'count': 10...
1  tt8579674  [{'age': 'all', 'avg_rating': 8.6, 'count': 94...
2  tt7286456  [{'age': 'all', 'avg_rating': 8.6, 'count': 59...
3  tt1302006  [{'age': 'all', 'avg_rating': 8.1, 'count': 18...
4  tt7131622  [{'age': 'all', 'avg_rating': 7.8, 'count': 32...
5  tt8637428  [{'age': 'all', 'avg_rating': 7.7, 'count': 21...

其中评级值是一个实际列表,而不是一个字符串(如果它们是一个字符串,x['ratings'] = x.ratings.apply(eval)将它们转换为一个对象)

首先,要将列表中的每一行分解为一组行:

parsed = x.groupby('movie_id').ratings.apply(lambda x: pd.DataFrame(x.values[0])).reset_index()

这将给你:

> parsed.head(10)
    movie_id  level_1    age  avg_rating   count
0  tt1302006        0    all         8.1  187675
1  tt1302006        1    <18         8.7     461
2  tt1302006        2  18-29         8.3   41951
3  tt1302006        3  30-44         7.9   59729
4  tt1302006        4    45+         7.8   18550
5  tt7131622        0    all         7.8  323152
6  tt7131622        1    <18         8.4     955
7  tt7131622        2  18-29         7.9   82133
8  tt7131622        3  30-44         7.6   95878
9  tt7131622        4    45+         7.5   26383
...

等等

这是关键的一步。它类似于您尝试的apply(pd.Series)步骤,但区别在于groupby。这允许我们在每个电影id中返回多行,而不是试图将返回的内容解释为一行。这感觉有点像黑客,但嘿,它是有效的

现在,您可以专注于计数&;获得列表值的评级:

tabulated= parsed.pivot_table(
    index='movie_id',
    columns=['age'],
    values=['avg_rating','count'],
    aggfunc='mean'
)

我在这里使用的意思是,假设每部电影和年龄组只有一行数据,sum也会起作用

> tabulated
          avg_rating                        count                             
age            18-29 30-44  45+  <18  all   18-29   30-44    45+   <18         all
movie_id                                                                      
tt1302006        8.3   7.9  7.8  8.7  8.1   41951   59729  18550   461      187675
tt7131622        7.9   7.6  7.5  8.4  7.8   82133   95878  26383   955      323152
tt7286456        8.7   8.5  8.3  9.1  8.6  160506  160158  30451  2244      592441
tt7653254        8.3   8.0  7.7  8.8  8.1   29740   33012   7875   318      109326
tt8579674        8.7   8.5  8.3  9.1  8.6    2437    2529    960    35        9420
tt8637428        7.9   7.6  7.3  8.0  7.7    5901    6492   2133    45       21362

相关问题 更多 >