主要利用pandas工具包对于MovieLens数据集进行操作练习,为《利用Python进行数据分析》的书上实例,具体是14.2 MovieLens 1M Dataset(MovieLens 1M数据集)
中文版Jupyter nbviewer地址:https://nbviewer.jupyter.org/github/LearnXu/pydata-notebook/tree/master/Chapter-01/
原文版地址为https://github.com/wesm/pydata-book/blob/2nd-edition/ch14.ipynb
本文代码地址https://github.com/ritarae/DataAnalysis
Jupyter Nbviewer版http://nbviewer.jupyter.org/github/ritarae/DataAnalysis/tree/master/
都为jupyter notebook格式的代码文件,环境jupyter notebook+python2.
1.MovieLens 1M Dataset(MovieLens 1M数据集)
这个数据集是电影评分数据:包括电影评分,电影元数据(风格类型,年代)以及关于用户的人口统计学数据(年龄,邮编,性别,职业等)。
下载地址:https://grouplens.org/datasets/movielens/1m/
还有一个MovieLens 20M Dataset(https://grouplens.org/datasets/movielens/)
MovieLens 1M数据集含有来自6000名用户对4000部电影的100万条评分数据。分为三个表:评分,用户信息,电影信息。
1.1数据预处理
这些数据都是dat文件格式,可以通过pandas.read_table将各个表分别读到一个pandas DataFrame对象中。
import pandas as pd
#用户信息(users.dat表,数据无表目信息)
unames = ['user_id', 'gender', 'age', 'occupation', 'zip']
users = pd.read_table('../datasets/movielens/users.dat', sep='::',
header=None, names=unames, engine='python')
#评分信息
rnames = ['user_id', 'movie_id', 'rating', 'timestamp']
ratings = pd.read_table('../datasets/movielens/ratings.dat', sep='::', header=None, names=rnames, engine='python')
#电影信息
mnames = ['movie_id', 'title', 'genres']
movies = pd.read_table('../datasets/movielens/movies.dat', sep='::', header=None, names=mnames, engine='python')
查看信息,加载前几行验证一下数据加载工作是否顺利。

将所有的数据都合并到一个表中的话,问题就简单多了。我们先用pandas的merge函数将ratings和users合并到一起,然后再将movies也合并进去。pandas会根据列名的重叠情况推断出哪些列是合并(或连接)键.
data=pd.merge(pd.merge(ratings,users),movies)
1.2 计算电影平均得分
利用数据透视表(pivot_table方法),可计算同一部电影不同性别的平均评分。
mean_ratings=data.pivot_table('rating',index=["title"],columns=["gender"],aggfunc='mean')
| gender | F | M |
|---|---|---|
| title | ||
| $1,000,000 Duck (1971) | 3.375000 | 2.761905 |
| 'Night Mother (1986) | 3.388889 | 3.352941 |
| 'Til There Was You (1997) | 2.675676 | 2.733333 |
| 'burbs, The (1989) | 2.793478 | 2.962085 |
| ...And Justice for All (1979) | 3.828571 | 3.689024 |
1.3 数据过滤
过滤掉评分数据不够250条的电影(这个数字可以自己设定)。
为了达到这个目的,我们先对title进行分组,然后利用size()得到一个含有各电影分组大小的Series对象。
active_titles中的电影,都是评论是大于250条以上的。我们可以用这些标题作为索引,从mean_ratings中选出这些评论大于250条的电影
#分组
ratings_by_title = data.groupby('title').size()
#数据过滤
active_titles = ratings_by_title.index[ratings_by_title >= 250]
#数据筛选
mean_ratings = mean_ratings.loc[active_titles]
1.4 数据排序
查看女性观众喜欢的电影,可以按F列进行降序操作:
top_female_ratings = mean_ratings.sort_values(by='F', ascending=False)
| gender | F | M |
|---|---|---|
| title | ||
| Close Shave, A (1995) | 4.644444 | 4.473795 |
| Wrong Trousers, The (1993) | 4.588235 | 4.478261 |
| Sunset Blvd. (a.k.a. Sunset Boulevard) (1950) | 4.572650 | 4.464589 |
| Wallace & Gromit: The Best of Aardman Animation (1996) | 4.563107 | 4.385075 |
| Schindler's List (1993) | 4.562602 | 4.491415 |
| Shawshank Redemption, The (1994) | 4.539075 | 4.560625 |
| Grand Day Out, A (1992) | 4.537879 | 4.293255 |
| To Kill a Mockingbird (1962) | 4.536667 | 4.372611 |
| Creature Comforts (1990) | 4.513889 | 4.272277 |
| Usual Suspects, The (1995) | 4.513317 | 4.518248 |
1.5 计算评分分歧
假设我们想要找出男性和女性观众分歧最大的电影。一个办法是给mean_ratings加上一个用于存放平均得分之差的列,并对其进行排序:
mean_ratings['diff'] = mean_ratings['M'] - mean_ratings['F']
sorted_by_diff = mean_ratings.sort_values(by='diff')
sorted_by_diff[:10]
| gender | F | M | diff |
|---|---|---|---|
| title | |||
| Dirty Dancing (1987) | 3.790378 | 2.959596 | -0.830782 |
| Jumpin' Jack Flash (1986) | 3.254717 | 2.578358 | -0.676359 |
| Grease (1978) | 3.975265 | 3.367041 | -0.608224 |
| Little Women (1994) | 3.870588 | 3.321739 | -0.548849 |
| Steel Magnolias (1989) | 3.901734 | 3.365957 | -0.535777 |
| Anastasia (1997) | 3.800000 | 3.281609 | -0.518391 |
| Rocky Horror Picture Show, The (1975) | 3.673016 | 3.160131 | -0.512885 |
| Color Purple, The (1985) | 4.158192 | 3.659341 | -0.498851 |
| Age of Innocence, The (1993) | 3.827068 | 3.339506 | -0.487561 |
| Free Willy (1993) | 2.921348 | 2.438776 | -0.482573 |
对行进行反序操作,并取出前15行,得到的则是男性更喜欢,而女性评价较低的电影:
sorted_by_diff[::-1][:10]
| gender | F | M | diff |
|---|---|---|---|
| title | |||
| Good, The Bad and The Ugly, The (1966) | 3.494949 | 4.221300 | 0.726351 |
| Kentucky Fried Movie, The (1977) | 2.878788 | 3.555147 | 0.676359 |
| Dumb & Dumber (1994) | 2.697987 | 3.336595 | 0.638608 |
| Longest Day, The (1962) | 3.411765 | 4.031447 | 0.619682 |
| Cable Guy, The (1996) | 2.250000 | 2.863787 | 0.613787 |
| Evil Dead II (Dead By Dawn) (1987) | 3.297297 | 3.909283 | 0.611985 |
| Hidden, The (1987) | 3.137931 | 3.745098 | 0.607167 |
| Rocky III (1982) | 2.361702 | 2.943503 | 0.581801 |
| Caddyshack (1980) | 3.396135 | 3.969737 | 0.573602 |
| For a Few Dollars More (1965) | 3.409091 | 3.953795 | 0.544704 |
2. MovieLens 20M数据集
基本过程相似
import pandas as pd
#用read_csv方法,源数据有表目
ratings=pd.read_csv('C:\\data\\datasets\\movielens\\ml-20m\\ratings.csv',header=0)
movies=pd.read_csv('C:\\data\\datasets\\movielens\\ml-20m\\movies.csv',header=0)


数据文件合并
data=ratings.merge(movies,on='movieId')
汇总评论数
rating_by_title=data.groupby('title').size()
按评论数降序排列
rating_by_title.sort_values(ascending=False)[:10]
title
Pulp Fiction (1994) 67310
Forrest Gump (1994) 66172
Shawshank Redemption, The (1994) 63366
Silence of the Lambs, The (1991) 63299
Jurassic Park (1993) 59715
Star Wars: Episode IV - A New Hope (1977) 54502
Braveheart (1995) 53769
Terminator 2: Judgment Day (1991) 52244
Matrix, The (1999) 51334
Schindler's List (1993) 50054
dtype: int64
#筛选一万以上的评论
active_title=rating_by_title.index[rating_by_title>=10000]
#得出这部分影片的平均分
mean_ratings=data.pivot('rating','title',aggfunc='mean')
mean_ratings=mean_ratings.ix[active_title]
#按分数从多到少排序
mean_ratings.sort_values(by=['rating'],ascending=False)
#评论数与评分差距较大的电影
rating_std_by_title=data.groupby('title')['rating'].std()
rating_std_by_title.sort_values(ascending=False)
本文利用pandas对MovieLens 1M数据集进行分析,包括数据预处理、计算电影平均得分、数据过滤、排序及评分分歧计算。通过数据透视表计算不同性别对电影的平均评分,并找出评分分歧大的电影。此外,还简要提及了MovieLens 20M数据集的处理。
410

被折叠的 条评论
为什么被折叠?



