一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情。
任务2:Movienles介绍
下载并读取Movielens 1M数据集(用户、电影、评分)
下载地址:grouplens.org/datasets/mo…
(下载很慢,非常慢......)
- MovieLens 1M 数据集,包含6k个用户在近4k部电影上的1亿条评论。
- 数据集分为三个文件:用户数据users.dat,电影数据movies.dat和评分数据ratings.dat。
- 这些数据都是dat文件格式 用户数据
分别有用户ID、性别、年龄、职业ID和邮编等字段
| UserID | Gender | Age | Occupation | Zip-code |
|---|
电影数据
分别有电影ID、电影名和电影风格等字段。
| MovieID | Title | Genres |
|---|
评分数据
分别有用户ID、电影ID、评分和时间戳等字段。
| UserID | MovieID | Rating | Timestamp |
|---|
统计如下指标:
- 总共包含多少用户?
- 6040个用户
users.shape[0]
# 6040
len(users['user_id'].unique())
# 6040
- 总共包含多个电影?
- 3883部电影,其中3706个电影被评分
movies.shape[0]
# 3883
movies['movie_id'].value_counts().sum()
# 3883
ratings['movie_id'].unique().shape
# 3706
- 平均每个用户对多少个电影进行了评分?
- 165,6部电影
Average_user_ratingt = ratings['user_id'].value_counts().sort_index()
Average_user_ratingt = Average_user_ratingt.to_frame().reset_index()
Average_user_ratingt.columns = ['user_id', 'Count']
#Average_user_ratingt.head()
Average_user_ratingt.describe()
# 平均每个用户评了165.6部电影
- 每部电影 & 每个用户的平均评分是?
- 下列code返回的dataframe即结果
# 每部电影的平均评分
Movie_Rating_sum = ratings.drop(['user_id', 'timestamp'], axis=1).groupby('movie_id').mean()
# 每个用户的平均评分
User_Rating_avg = ratings.drop(['movie_id', 'timestamp'], axis=1).groupby('user_id').mean()
- 如果你来进行划分数据集为训练和验证,你会如何划分?
- 因为user_id和movie_id会发生交互,所以,如果按照传统的训练集测试集划分方法,对data按照一定的比例进行划分,可能会导致,有部分用户or电影没有出现在训练集中,即,训练集中缺少部分用户or电影
- 所以,要考虑,所有user_id是否都出现在train中,所有movie_id是否都出现在train中
- 参考其他同学的观点,以下3种思路:
- 保证每个用户都出现在训练集当中,对每一个用户的打分数据,按比例划分训练集和测试集
- 保证每部电影都出现在训练集当中:对每一部电影的打分数据,按照比例进行划分训练集和测试集
- 保证每一部电影和用户都出现在训练集当中,这种划分方式相较于上面的两种划分方式稍微有些复杂。
遇到的问题
1. 数据读取
第一次处理.dat结尾的数据 要用到read_table
read_table是一个数据读入工具,将数据读入到一个DataFrame中,例如,在本次数据处理的例子中,
import numpy as np
import pandas as pd
users = pd.read_table('users.dat')
users.head()
# 数据呈现出 2::M::56::16::70072 的形式,且没有列名
所以,应该这样读取
import numpy as np
import pandas as pd
uname = ['user_id', 'gender', 'age', 'occupation', 'zip']
users = pd.read_table('users.dat', sep='::', header=None, names=uname,engine='python')
users.head()
sep=' ':表示的是分隔符,比如说,在这个例子中,原数据集是以::来分隔的,所以我们的分隔符是'::',如果是txt文件,则我们的分隔符是制表符,‘\t’
header=None 表示txt文件的第一行不是列的名字,是数据。如果你的数据集一开始的第一列是数据名称,则不需要加这个,如果不是,则需要表示出来没有标题。
names表示这个DataFrame的标题是什么
这样,才会得到正确格式的DataFrame
2.编码格式
使用如下code读取数据,会报错
import pandas as pd
mname = ['movie_id','title','genres']
movies = pd.read_table('movies.dat',sep='::', header=None, names=mname,engine='python')
报错: 'utf-8' codec can't decode byte 0xe9 in position 3114: invalid continuation byte
解决方法:将编码改为:ISO-8859-1, 增加 encoding='ISO-8859-1' 可解决
```python
import pandas as pd
uname = ['user_id', 'gender', 'age', 'occupation', 'zip']
users = pd.read_table('users.dat', sep='::', header=None, names=uname,engine='python',encoding='ISO-8859-1')
mname = ['movie_id','title','genres']
movies = pd.read_table('movies.dat',sep='::', header=None, names=mname,engine='python',encoding='ISO-8859-1')
3. dataframe某一列的去重值的个数
#dataframe某一列的去重值的个数
len(movies['movie_id'].unique())
4. dataframe合并(merge)
#使用merge 函数将3个表进行合并
data = pd.merge(pd.merge(ratings, users), movies)
print(data.head())