写在前面
本人是统计学本科大四, 一直以来都使用的是R语言进行数据分析,但由于以后读定量金融 + 找寒假实习,才发现现在都需要掌握python进行数据分析,于是我打算利用有限的时间自学,参考书籍是有名的Wes McKinney的《利用python进行数据分析》,由于书籍出版较早,里面的py版本也是2.7,所以我结合新的版本进行了改变,希望对入门的大家有用,使用的是macOS + jupyter notebook。
数据导入
这里使用的是书中第二章的第二个data,是来自https://grouplens.org/datasets/movielens/的MovieLens 1M Dataset数据集,这些数据中包含电影评分、电影数据(风格和年代)以及关于用户的人口统计学数据(年龄、邮编、性别和职业等)。其中包含了来自6000名用户对4000部电影的100万条评分数据。 它分为三个表:评分、用户信息和电影信息。从zip解压后,可以通过pandas.read_table将各个表读到pandas DataFrame对象中:
import pandas as pd
unames = ['user_id', 'gender', 'age', 'occupation', 'zip']
users = pd.read_table('/Users/vicky/Desktop/ml-1m/ml-1m/users.dat', sep='::', header=None, names=unames)
rnames = ['user_id', 'movie_id', 'rating', 'timestamp']
ratings = pd.read_table('/Users/vicky/Desktop/ml-1m/ml-1m/ratings.dat', sep='::', header=None, names=rnames)
mnames = ['movie_id', 'title', 'genres']
movies = pd.read_table('/Users/vicky/Desktop/ml-1m/ml-1m/movies.dat', sep='::', header=None, names=mnames)
利用切片语法进行查看(切片听起来很高级其实也是R里面常用的啦,就是筛选几行)
users[:5]
ratings[:5]
movies[:5]
理论上如下图:
users:
![](https://i-blog.csdnimg.cn/blog_migrate/d2eabb75788e65f651a0491c58f7de17.png)
ratings:
![](https://i-blog.csdnimg.cn/blog_migrate/1e9ba5c448a47a95b1feb608b5b9560a.png#pic_center)
movies:
![](https://i-blog.csdnimg.cn/blog_migrate/fd536e2a4c85b703c92b4b5bd9794240.png#pic_center)
表格合并
这真的是个很神奇的功能,侧面体现了python的数据分析的强大之处,在实际中也有很广泛的应用,比如给你许多股票的一个月数据,你可以通过按照股票代码合并,得到每一支股票的每一天的变化.
data=pd.merge(pd.merge(ratings,users),movies)
data
解释一下上面的代码,我们先把ratings和users合并,寻找它们共同的列,应该是user_id,再进一步和movies合并,那应该是按movie_id 合并,这个过程其实比较智能,pandas会自己判断的。
理论结果如下:
进一步,我们可以根据任意个用户或电影属性对评分数据进行聚合操作,例如我们要按性别计算每部电影的平均得分,可以使用pivot_table方法:
mean_ratings = data.pivot_table('rating', index='title', columns='gender', aggfunc ='mean')
得到结果如下:
![](https://i-blog.csdnimg.cn/blog_migrate/b00c3f5b1755dfa88ca17f7eec2ac821.png#pic_center)
该操作产生了另一个DataFrame,其内容为电影平均得分,行标(index)为电影名,列标为性别。
数据过滤
现在我们打算过滤掉数据不够250条的电影,为了达到这个目的,我先对title进行分组,然后利用size()得到一个含有各电影分组大小的Series对象:
ratings_by_title = data.groupby('title').size() #对title进行分组,然后利用size()得到一个含有各电影分组大小的Series对象
active_titles = ratings_by_title.index[ratings_by_title >= 250] #过滤掉评分数据不够250条的电影
该索引中含有评分数据大于250条的电影名称,然后我们就可以据此从前面的mean_ratings中选取所需的行了:
mean_ratings = mean_ratings.loc[active_titles]#pandas中DataFrame的ix已经不能使用,因为最新版本已经取消ix了
为了了解女性观众最喜欢的电影,我们可以对F列进行降序排序:
top_female_ratings = mean_ratings.sort_values( by ='F',ascending=False )
得到结果如下:
计算评分分歧
假设我们想要找出男性与女性观众分歧最大的电影,一个方法是给mean_ratings加上一个用于存放平均得分之差的列,对其进行排序:
mean_ratings['diff'] = mean_ratings['M']-mean_ratings['F']
sorted_by_diff= mean_ratings.sort_values(by='diff')
按“diff”排序,即得到分歧最大且女性观众更喜欢的电影:
如果只是想得到分歧最大的电影(不考虑性别因素),则可以计算得分数据的方差或标准差:
rating_std_by_title = data.groupby('title')['rating'].std()
rating_std_by_title = rating_std_by_title.loc[active_titles]```
rating_std_by_title.sort_values(ascending=False)[:10]
得到结果:
![](https://i-blog.csdnimg.cn/blog_migrate/211143a37f95066190484d31f9855fb6.png#pic_center)