【推荐系统】Coggle 30 Days of ML(22年4月)打卡 Day 2

267 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情

任务2:Movienles介绍

下载并读取Movielens 1M数据集(用户、电影、评分)

下载地址:grouplens.org/datasets/mo…

(下载很慢,非常慢......)

  • MovieLens 1M 数据集,包含6k个用户在近4k部电影上的1亿条评论。
  • 数据集分为三个文件:用户数据users.dat,电影数据movies.dat和评分数据ratings.dat。
  • 这些数据都是dat文件格式 用户数据

分别有用户ID、性别、年龄、职业ID和邮编等字段

UserIDGenderAgeOccupationZip-code

电影数据

分别有电影ID、电影名和电影风格等字段。

MovieIDTitleGenres

评分数据

分别有用户ID、电影ID、评分和时间戳等字段。

UserIDMovieIDRatingTimestamp

统计如下指标:

  • 总共包含多少用户?
    • 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())