数据分析案例(MovieLens)
2018-11-17 本文已影响157人
GHope
MovieLens 1M数据集
MovieLens 1M数据集含有来自6000名用户对4000部电影的100万条评分数据。它分为三个表:评分、用户信息和电影信息。
pd.options.display.max_rows = 10
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')
数据加载
查看每个DataFrame的前几行即可验证数据加载工作是否一切顺利:
users[:5]
ratings[:5]
movies[:5]
ratings
验证数据加载
想要根据性别和年龄计算某部电影的平均得分,如果将所有数据都合并到一个表中的话问题就简单多了。我们先用pandas的merge函数将ratings跟users合并到一起,然后再将movies也合并进去。pandas会根据列名的重叠情况推断出哪些列是合并(或连接)键
data = pd.merge(pd.merge(ratings, users), movies)
自动合并
按性别计算每部电影的平均得分,我们可以使用pivot_table方法(也可以用groundby对'title'和'gendef'分组之后unstack可以得到相同的结果)
mean_ratings = data.pivot_table('rating', index='title', columns='gender', aggfunc='mean')
按性别计算每部电影的平均得分
过滤掉评分数据不够250条的电影(随便选的一个数字)。为了达到这个目的,先对title进行分组,然后利用size()得到一个含有各电影分组大小的Series对象
ratings_by_title = data.groupby('title').size()
active_titles = ratings_by_title.index[ratings_by_title >= 250]
分组过后根据分组大小过滤不满足条件的数据
标题索引中含有评分数据大于250条的电影名称,然后我们就可以据此从前面的mean_ratings中选取所需的行了:
mean_ratings = mean_ratings.loc[active_titles]
选取所需数据
为了了解女性观众喜欢的电影,我们可以对F列降序排列:
top_female_ratings = mean_ratings.sort_values(by='F', ascending=False)
了解女性观众喜欢的电影
计算评分分歧
要找出男性和女性观众分歧大的电影。一个办法是给mean_ratings加上一个用于存放平均得分之差的列,并对其进行排序
mean_ratings['diff'] = mean_ratings['M'] - mean_ratings['F']
按”diff”排序即可得到分歧大且女性观众更喜欢的电影
sorted_by_diff = mean_ratings.sort_values(by='diff')
分歧大且女性观众更喜欢的电影
对排序结果反序并取出前10行,得到的则是男性观众更喜欢的电影
男性观众更喜欢的电影如果只是想要找出分歧⼤的电影(不考虑性别因素),则可以计算得分数据的方差或标准差, 在统计描述中,方差用来计算每一个变量(观察值)与总体均数之间的差异。
# Standard deviation of rating grouped by title
rating_std_by_title = data.groupby('title')['rating'].std()
# Filter down to active_titles
rating_std_by_title = rating_std_by_title.loc[active_titles]
# Order Series by value in descending order
rating_std_by_title.sort_values(ascending=False)[:10]
分歧⼤的电影