本次数据挖掘项目是电影推荐问题,目的是找出对象同时出现的情况,也就是寻找用户同时喜欢几部电影的情况。
使用最基础的Apriori算法。
import os
import pandas as pd
import numpy as np
import sys
from operator import itemgetter
from collections import defaultdict
一、加载数据并观察
# 文件的后缀就是.data,后面不要再加.csv了,否则会报错
all_ratings = pd.read_csv("u.data", delimiter='\t', header=None, names=["UserID","MovieID","Rating","Datetime"])
# 让我们看看冰山的一角吧
all_ratings.head()
UserID | MovieID | Rating | Datetime | |
---|---|---|---|---|
0 | 196 | 242 | 3 | 881250949 |
1 | 186 | 302 | 3 | 891717742 |
2 | 22 | 377 | 1 | 878887116 |
3 | 244 | 51 | 2 | 880606923 |
4 | 166 | 346 | 1 | 886397596 |
# 很好奇每一列都是什么数据类型,有没有缺失的记录呢?
all_ratings.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100000 entries, 0 to 99999
Data columns (total 4 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 UserID 100000 non-null int64
1 MovieID 100000 non-null int64
2 Rating 100000 non-null int64
3 Datetime 100000 non-null int64
dtypes: int64(4)
memory usage: 3.1 MB
每一列都是int类型且没有缺失,很好,数据处理不用再做缺失值处理了。
# 再看看数据大小吧,其实从info()里也能看出来的,不过这样更直接,一眼就看出来啦
all_ratings.shape
(100000, 4)
# 去个重吧,万一有重复的数据
print("去重前数据大小:{0}".format(all_ratings.shape))
all_ratings.drop_duplicates(keep="first",inplace=True)
print("去重后数据大小:{0}".format(all_ratings.shape))
去重前数据大小:(100000, 4)
去重后数据大小:(100000, 4)
没有重复的呢。
# 看看都有哪些用户爱看电影还给电影打了分吧(反正我看电影是不喜欢打分的)
all_ratings["UserID"].value_counts()
405 737
655 685
13 636
450 540
276 518
...
147 20
19 20
572 20
636 20
895 20
Name: UserID, Length: 943, dtype: int64
一共有943名用户,用户#405竟然给737部电影打了分,最少的也有20部。
# 让我们看看都有哪些电影被打了分吧
all_ratings["MovieID"].value_counts()
50 583
258 509
100 508
181 507
294 485
...
1648 1
1571 1
1329 1
1457 1
1663 1
Name: MovieID, Length: 1682, dtype: int64
一共有1682部电影被观看并打分,电影#50被打分次数最多有583次,有的电影就有点惨了只被打过一次分比如电影#1663。
# 看下电影分数都有哪几档
all_ratings["Rating"].unique().tolist()
[3, 1, 2, 4, 5]
# 解析时间戳,日期看着比一串数字方便多了
all_ratings["Datetime"] = pd.to_datetime(all_ratings["Datetime"], unit='s')
all_ratings.head()
UserID | MovieID | Rating | Datetime | |
---|---|---|---|---|
0 | 196 | 242 | 3 | 1997-12-04 15:55:49 |
1 | 186 | 302 | 3 | 1998-04-04 19:22:22 |
2 | 22 | 377 | 1 | 1997-11-07 07:18:36 |
3 | 244 | 51 | 2 | 1997-11-27 05:02:03 |
4 | 166 | 346 | 1 | 1998-02-02 05:33:16 |
看样子都是很古老的数据啊
二、Apriori算法的实现
# 首先确定用户是不是喜欢某一部电影,评分高于3的认定为喜欢
all_ratings['Favorable'] = all_ratings['Rating'] > 3
# 从数据集选取一部分用作训练集,能减少搜索空间,提升算法的速度
# 我尝试用UserID前200的数据训练,电脑直接卡住,建议先用50以内的数值尝试,如果执行起来很流畅再调高
ratings = all_ratings[all_ratings['UserID'].isin(range(20))]
# 选取用户喜欢某部电影的数据行
favorable_ratings =