当前位置:   article > 正文

MovieLens个性化电影推荐系统实战(一):数据探索(数据预处理、数据可视化)_movielens数据集下载

movielens数据集下载

一、前言

        本系列文章使用MovieLens数据集进行机器学习综合实战。本文主要记录的是数据预处理、数据可视化。由于平台有点鸡肋,不能显示运行代码块的结果,大家可以在评论区留言或私信我获取有结果显示的源码。文章和代码均是小编原创,为小编的期末实训项目。仅供大家参考,请勿全篇抄袭本文!!

系列文章目录:

MovieLens个性化电影推荐系统实战(二):用户群体划分(聚类)-CSDN博客

MovieLens个性化电影推荐系统实战(三):个性化电影推荐(推荐算法)-CSDN博客

资料:

MovieLens个性化电影推荐系统实战——系列文章资料-CSDN博客

文章资源,百度网盘永久有效:

链接: https://pan.baidu.com/s/1P45bvnp6ezE-0J06Wjx2sQ?pwd=csdn 提取码: csdn 复制这段内容后打开百度网盘手机App,操作更方便哦

二、数据集介绍

        数据集链接:https://files.grouplens.org/datasets/movielens/ml-1m.zip

        若无法下载,评论区留言或私信获取数据集。

        MovieLens数据集是一个经典的电影评分数据集,由GroupLens Research实验室收集整理。该数据集包含了用户对电影的评分和观看记录,以及电影本身的元数据信息,如电影类型、导演、演员等。

        MovieLens数据集可以用于推荐系统的研究和开发,通过分析用户对电影的评分和观看习惯,可以构建个性化的推荐算法,为用户提供更好的电影推荐。此外,MovieLens数据集还可以用于用户行为分析、市场调研和商业决策,以及数据挖掘和机器学习等领域的研究和应用。

        MovieLens数据集是一个公开的数据集,可以从GroupLens Research实验室的网站上进行下载。同时,还有一些第三方网站提供MovieLens数据集的下载和使用,如Kaggle、GitHub等。在使用MovieLens数据集时需要注意保护用户隐私和数据安全。

        本文章使用ml-1m数据集,稳定的基准数据集。6000 名用户在 4000 部电影上获得了 100 万次评分。在2003 年 2 月发布。

三、数据集导入以及查看

  1. unames = ['user_id', 'gender', 'age', 'occupation', 'zip']
  2. user_df = pd.read_csv('users.dat',
  3. sep='::',
  4. header=None,
  5. names=unames,
  6. engine='python')
  7. # 电影信息
  8. mnames = ['movie_id', 'title', 'genres']
  9. movies_df = pd.read_csv('movies.dat',
  10. sep='::',
  11. header=None,
  12. names=mnames,
  13. engine='python',
  14. encoding='ISO-8859-1')
  15. # 评分信息
  16. rnames = ['user_id', 'movie_id', 'imdbId', 'timestamp']
  17. ratings_df = pd.read_csv('ratings.dat',
  18. sep='::',
  19. header=None,
  20. engine='python',
  21. names=rnames)

年龄分段
* 1: "Under 18"
* 18: "18-24"
* 25: "25-34"
* 35: "35-44"
* 45: "45-49"
* 50: "50-55"
* 56: "56+"
职业
* 0: "other" or not specified
* 1: "academic/educator"
* 2: "artist"
* 3: "clerical/admin"
* 4: "college/grad student"
* 5: "customer service"
* 6: "doctor/health care"
* 7: "executive/managerial"
* 8: "farmer"
* 9: "homemaker"
* 10: "K-12 student"
* 11: "lawyer"
* 12: "programmer"
* 13: "retired"
* 14: "sales/marketing"
* 15: "scientist"
* 16: "self-employed"
* 17: "technician/engineer"
* 18: "tradesman/craftsman"
* 19: "unemployed"
* 20: "writer"

四、数据预处理

去除电影名字段的年份。

  1. #使用正则表达式去除title字段的年份
  2. import re
  3. patter = re.compile(r'^(.*)\((\d+)\)$')
  4. title = {val: patter.match(val).group(1) for i, val in enumerate(set(movies_df['title']))}
  5. movies_df['title'] = movies_df['title'].map(title)
  6. movies_df.head()

将性别字段编码,不知道后面有没有用,下意识的处理。

  1. #将性别字段进行数值编码
  2. from sklearn.preprocessing import LabelEncoder
  3. # 假设df是你的数据框,其中"color"是一个分类变量
  4. le = LabelEncoder()
  5. user_df['gender_encoding'] = le.fit_transform(user_df['gender'])
  6. # user_df.drop(['gender'], axis=1, inplace=True)
  7. user_df.head()

查看重复值,需要一行一行运行。结果是没有重复值。

  1. #重复值查看以及处理
  2. user_df.duplicated().value_counts()
  3. movies_df.duplicated().value_counts()
  4. ratings_df.duplicated().value_counts()

异常值查看,使用描述性统计,乍一看是没有异常值的。

user_df.describe()

画出箱线图,确定了确实没有异常值。

  1. import seaborn as sns
  2. import matplotlib.pyplot as plt
  3. # 提取所有特征列
  4. feature_columns = user_df.columns
  5. # 创建一个包含多个子图的画布
  6. fig, axes = plt.subplots(nrows=1, ncols=len(feature_columns), figsize=(20, 5))
  7. # 遍历每个特征并绘制箱线图
  8. for i, feature in enumerate(feature_columns):
  9. sns.boxplot(x=feature, data=user_df, ax=axes[i])
  10. axes[i].set_title(feature) # 设置子图标题
  11. plt.tight_layout() # 自动调整子图布局
  12. plt.show()
  13. #观察描述性统计和箱线图,数据集无异常值,年龄为1表示18岁以下

五、数据可视化

1、评分维度分析

  1. #评分人数和平均评分的气泡图
  2. import plotly.express as px
  3. movie_stats = ratings_df.groupby('movie_id').agg({'imdbId': ['mean', 'count']})
  4. movie_stats.columns = movie_stats.columns.droplevel(0)
  5. movie_stats = movie_stats.rename(columns={'mean': 'mean_rating', 'count': 'rating_count'})
  6. movie_stats = movie_stats[movie_stats['rating_count'] >= 50].iloc[:200, :]
  7. fig = px.scatter(movie_stats, x='mean_rating', y='rating_count', hover_name=movie_stats.index, size='rating_count',
  8. color='mean_rating',
  9. labels={'mean_rating': 'Mean Rating', 'rating_count': 'Rating Count'}, title='Movie Ratings')
  10. fig.show()

将鼠标放上去有交互的,这里做不到。评分最高同时评论数最高的是id为260的电影。

  1. #用户评论数与平均评分气泡图
  2. user_stats = ratings_df.groupby('user_id').agg({'imdbId': ['mean', 'count']})
  3. user_stats.columns = user_stats.columns.droplevel(0)
  4. user_stats = user_stats.rename(columns={'mean': 'mean_rating', 'count': 'rating_count'})
  5. user_stats = user_stats[user_stats['rating_count'] >= 50].iloc[:100, :]
  6. fig = px.scatter(user_stats, x='mean_rating', y='rating_count', hover_name=user_stats.index, size='rating_count',
  7. color='mean_rating',
  8. labels={'mean_rating': 'Mean Rating', 'rating_count': 'Rating Count'}, title='User Ratings')
  9. fig.show()

可以看出是哪位宝宝在恶评!!!!

  1. rating_val_count = ratings_df.imdbId.value_counts()
  2. fig = px.bar(rating_val_count, x=rating_val_count.index, y=rating_val_count, text=rating_val_count,
  3. labels={
  4. "index": "Ratings",
  5. 'y': 'Number of Ratings'},
  6. color=rating_val_count
  7. )
  8. fig.update_traces(textposition='outside')
  9. fig.update_layout(title_text='Frequency of the Ratings',
  10. title_x=0.5, title_font=dict(size=24))
  11. fig.update_traces(marker=dict(line=dict(color='#000000', width=2)))
  12. fig.update_layout({'plot_bgcolor': 'rgba(0, 0, 0, 0)'})
  13. fig.show()

可以看到,大多数平分分布在3分到5分。说明电影质量杠杠的!!世界上还是好人多。

2、用户维度分析

  1. #职业用户人数占比
  2. users_by_occupation = user_df.groupby('occupation').size()
  3. # 对用户人数进行排序
  4. sorted_users_by_occupation = users_by_occupation.sort_values(ascending=False)
  5. sorted_users_by_occupation.plot(kind='bar')
  6. plt.xlabel('Occupation')
  7. plt.ylabel('Number of Users')
  8. plt.title('User Counts by Occupation (Sorted)')
  9. plt.show()

看出来了,职业ID为4、0、7的评论电影的打工人很多,可能是这三种职业的人比较爱表达自己的看法,喜欢分享自己的感受。

  1. # 根据年龄对用户进行分组,并统计每个年龄段的用户数量
  2. users_by_age = user_df.groupby('age').size()
  3. users_by_age.plot(kind='bar')
  4. plt.xlabel('Age')
  5. plt.ylabel('Number of Users')
  6. plt.title('User Counts by Age')
  7. plt.show()
  8. #观察柱状图,符合正态分布

25-34这个年龄段的人,似乎有很多想分享的!!

  1. #用户男女性别占比
  2. users_by_gender = user_df['gender'].value_counts()
  3. users_by_gender.plot(kind='pie', autopct='%1.1f%%')
  4. plt.axis('equal')
  5. plt.title('User Gender Distribution')
  6. plt.show()

男性占比7成!!女生不喜欢分享吗??

3、电影维度分析

  1. movies_data = pd.concat([movies_df, movies_df['genres'].str.get_dummies(sep='|')], axis=1)
  2. movies_data.drop('genres', axis=1, inplace=True)
  3. #%%
  4. #每个职业,用户最关注的电影类型(最关注的电影类型,非最喜欢的电影类型,即评论数最多的电影类型)
  5. merged_data = pd.merge(pd.merge(user_df, ratings_df), movies_data)
  6. genre_columns = ['Action', 'Adventure', 'Animation', "Children\'s", 'Comedy', 'Crime', 'Documentary', 'Drama',
  7. 'Fantasy', 'Film-Noir', 'Horror', 'Musical', 'Mystery', 'Romance', 'Sci-Fi', 'Thriller', 'War',
  8. 'Western']
  9. genre_by_occupation = merged_data.groupby('occupation')[genre_columns].sum()
  10. # 计算每个职业对所有电影类型的评论数
  11. total_ratings_by_occupation = genre_by_occupation.sum(axis=1)
  12. # 计算每个职业对每种电影类型的评论数比例
  13. genre_proportions_by_occupation = genre_by_occupation.divide(total_ratings_by_occupation, axis=0)
  14. plt.figure(figsize=(12, 8))
  15. genre_proportions_by_occupation.plot(kind='bar', stacked=True)
  16. plt.title('Proportions of Genre Ratings by Occupation')
  17. plt.xlabel('Occupation')
  18. plt.ylabel('Proportion of Ratings')
  19. plt.legend(title='Genre', bbox_to_anchor=(1.05, 1), loc='upper left')
  20. plt.show()

可以看出,大家都关注戏剧和喜剧。但是不同的职业,对其他的电影类型关注度不同。

  1. reviews_by_genre = merged_data.iloc[:, 10:].sum()
  2. reviews_by_genre = reviews_by_genre.sort_values(ascending=False)
  3. reviews_by_genre.plot(kind='bar')
  4. plt.xlabel('Genre')
  5. plt.ylabel('Number of Reviews')
  6. plt.title('Review Counts by Genre')
  7. plt.show()

总的来看,大家很关注戏剧和喜剧,但是记录片不为大家所关注,但是某些用户肯定是喜欢的。这就为后面构建推荐系统提供细节,不放过任何电影推荐细节。

  1. #每个性别用户最关注的电影类型(最关注的电影类型,非最喜欢的电影类型,即评论数最多的电影类型)
  2. genre_by_gender = merged_data.groupby('gender')[genre_columns].sum()
  3. total_ratings_by_gender = genre_by_gender.sum(axis=1)
  4. # 计算每个职业对每种电影类型的评论数比例
  5. genre_proportions_by_gender = genre_by_gender.divide(total_ratings_by_gender, axis=0)
  6. plt.figure(figsize=(12, 8))
  7. genre_proportions_by_gender.plot(kind='bar', stacked=True)
  8. plt.title('Proportions of Genre Ratings by Occupation')
  9. plt.xlabel('Occupation')
  10. plt.ylabel('Proportion of Ratings')
  11. plt.legend(title='Genre', bbox_to_anchor=(1.05, 1), loc='upper left')
  12. plt.show()

不难看出,男生更关注动作片,女生更关注喜剧和儿童片。

  1. #每个电影类型的电影数量
  2. genres_df = movies_df['genres'].str.get_dummies('|')
  3. # 计算每个电影类型的数量
  4. genre_counts = genres_df.sum().sort_values(ascending=False)
  5. genre_counts.plot(kind='bar')
  6. plt.title('Number of Movies per Genre')
  7. plt.xlabel('Genre')
  8. plt.ylabel('Count')
  9. plt.xticks(rotation=45)
  10. plt.tight_layout()
  11. plt.show()

怪不得戏剧和喜剧的关注度高,原来是拥有这两个元素的电影这么多啊!!!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/752526
推荐阅读
相关标签
  

闽ICP备14008679号