数据基础---预处理---spark学习之数据预处理和特征提取
发布日期:2021-07-24 12:00:50 浏览次数:1 分类:技术文章

本文共 4868 字,大约阅读时间需要 16 分钟。

MovieLens数据集介绍

MovieLens 100k数据集,下载地址:

MovieLens数据集保存了用户对电影的评分。基于这个数据集,我们可以测试一些推荐算法、评分预测算法。
MovieLens 100k
该数据集记录了943个用户对1682部电影的共100,000个评分,每个用户至少对20部电影进行了评分。
保存了该数据集的概要:
943 users
1682 items
100000 ratings
文件u.item保存了item的信息,也就是电影的信息,共1682部电影。每一行代表一部电影,格式如下

movie id | movie title | release date | video release date | IMDb URL | unknown | Action | Adventure | Animation | Children's | Comedy | Crime | Documentary | Drama | Fantasy |Film-Noir | Horror | Musical | Mystery | Romance | Sci-Fi | Thriller | War | Western |

比如第一行如下:

1|Toy Story (1995)|01-Jan-1995||http://us.imdb.com/M/title-exact?Toy%20Story%20(1995)|0|0|0|1|1|1|0|0|0|0|0|0|0|0|0|0|0|0|0

总共有1862行这样的数据。最后19个字段保存的是该电影的类型,一个字段对应一个类型,值为0代表不属于该类型,值为1代表属于该类型,类型信息保存在文件u.genre中。

文件u.genre保存了电影的类型信息。
文件u.user保存了用户的信息,共有943个用户,其id依次是1、2、……、943。文件中每一行保存了一个用户的信息,格式如下:

user id | age | gender | occupation | zip code 文件u.occupation保存了用户职业的集合。

具体如

1|24|M|technician|857112|53|F|other|94043

文件u.data保存了所有的评分记录,每一行是一个用户对一部电影的评分,共有100000条记录。当然,如果某用户没有对某电影评分,则不会包含在该文件中。评分的分值在1到5之间,就是1、2、3、5这5个评分。每一行格式如下:

user id | item id | rating | timestamp

具体如:

196	242	3	881250949186	302	3	89171774222	377	1	878887116244	51	2	880606923166	346	1	886397596298	474	4	884182806

其中,item id就是电影的id,时间戳timestamp是评分时间。可以自己对时间戳进行转换,一般在20世纪90年代。

将u.data按照80%/20%的比例分成u1.base和u1.test,可以将u1.base作为训练集,u1.test作为测试集。u2、u3、u4、u5系列文件和u1类似。u1、u2、u3、u4、u5的测试集是不相交的,它们可以用来做(5折交叉验证)5 fold cross validation。
文件ua.base和文件ua.test也是由u.data拆分而来,在ua.test中包含了每个用户对10部电影的评分,从u.data去掉ua.test得到ua.base。ub.base和ub.test也使用了同样的生成方法。另外,ua.test和ub.test是不相交的。

另外还可以下到更大的数据集

MovieLens 1M
该数据集保存的是6040个用户对3952部电影的1000209个评分记录。具体可以参考其README文件。
MovieLens 10M
71567个用户,10681部电影,10000054条评分记录,同时多了个用户为电影设置的标签。具体可以阅读其中的README.html。
Tag Genome
该数据集下有三个数据文件。
**movies.dat:**其每一行的格式是:

MoviePopularity是在MovieLens中对该电影的评分次数。

**tag.dat:**每一行的格式是:

是使用该Tag的用户数,一个用户最多算1次。

**tag_relevance.dat:**每一行的格式是:

的值在0和1之间,值越大,Tag与Movie的关联性越强。

数据探索

探索用户数据

要运行spark程序,即使是独立模式,或者直接在类似pycharm的软件中连接spark,也要先启动spark集群。

#先载入数据from pyspark import SparkConf,SparkContextfrom pyspark.sql import SparkSessionsc=SparkContext()user_data=sc.textFile("/home/digger/下载/ml-100k/u.user")#初步看一样数据的样子print(user_data.first())

结果如下:

1|24|M|technician|85711

从这样的数据里,我们可以对用户的年龄、性别、职业、地区进行统计(这里以邮编代替地区)

“ | ”字符来分隔各行数据,这将生成一个本地RDD,其中每一个记录对应一个Python列表,各列表由用户ID(user ID)、年龄(age)、性别(gender)、职业(occupation)和邮编(ZIP code)五个属性构成。

user_fields=user_data.map(lambda line:line.split('|'))num_user=user_fields.map(lambda field:field[0]).count()num_gender=user_fields.map(lambda field:field[2]).distinct().count()#distinct用于去重,count()用于计数num_occupation=user_fields.map(lambda field:field[3]).distinct().count()num_zipcode=user_fields.map(lambda field:field[4]).distinct().count()print("共有用户:%d户,性别:%d类,职业%d类,邮编:%d种"%(num_user,num_gender,num_occupation,num_zipcode))

结果如下:

共有用户:943户,性别:2类,职业21类,邮编:795种
#下面来查看年龄的分布import matplotlib.pyplot as pltimport seaborn as snsages= user_fields.map(lambda field:field[1]).colletct()#返回RDD的所有元素,方便后面对age进行统计,之后就可以利用单机的一切函数了ax=sns.distplot(ages)plt.show()

结果如下:

这里写图片描述
从上图可以看到,该网站的用户以年经人为主,尤其与27-30岁人群最多。

#下面统计职业的频率直方图occupations=user_fields.map(lambda field:field[3]).collect()#当数据不大时,我们可以用这种方法将所有元素收集起来ax=sns.countplot(x=occupations)plt.show()#当数据量很大的时候,不要直接用collect()的

上面的图形结果如下:

这里写图片描述
从图上可以看到,用户中人数排在前五的职业分别是学生、教育工作者、管理员、程序员和工程师。
**注意:**当数据量很大的时候,是不能用collect()的,要不整个集群卡死;此时如果需要展现数据的统计信息,应该先进行统计,统计的话就可以想办法设计成可拆分的任务,让各个节点进行一小块的统计任务,最后在汇总统计数据,数据量再大,汇总后也就那些指标,此时再来画图就很简单,可在单机上进行。而不应该边像上面那样直接将所有数据collect起来,然后直接画图,此时countplot同时承担了统计和画图的任务,对于大数据来讲,怎么吃得消呢。
另外,spark并不擅长画图这一类事情,个人觉得如果要统计消息,可以采取抽样的方式,在整个大数据集中获取一小部分数据,然后在单机上就可以利用这些统计类的画图函数来展示数据特点了。抽样本来就是我们认识客观世界的一种方式,初步展示不一定要大而全。
下面用分布式的思维进行统计和展示

occupation_count=user_fields.map(lambda fields:(fields[3],1))#这一步先每出现一次职业就计一次数,只要对这些数字求和就可以知道各个职业出现了多少次,即得到各职业的频率分布occupation_counts=occupation_count.reduceByKey(lambda x,y:x+y)#利用reduceByKey()函数对各条数据进行归并,达到统计目的occupation_counts=occupation_counts.collect()#此时不用担心数据量的问题,经过前面的shuffle过程,此时数据已经被归为有限的数目了,从前面对职业个数的统计知道,现在数据只有21对,前面是职业名称,后面是对应的人数print(occupation_counts)

结果如下:

[('engineer', 67), ('homemaker', 7), ('doctor', 7), ('administrator', 79), ('student', 196), ('programmer', 66), ('other', 105), ('executive', 32), ('retired', 14), ('artist', 28), ('none', 9), ('educator', 95), ('scientist', 31), ('lawyer', 12), ('writer', 45), ('technician', 27), ('librarian', 51), ('salesman', 12), ('healthcare', 16), ('marketing', 26), ('entertainment', 18)]
#下面提取出职业和对应的人数x_label=np.array([i[0] for i in occupation_counts])y=np.array([i[1] for i in occupation_counts])#我们先对统计结果进行排序以便于展现x_label=x_label[np.argsort(y)]y=y[np.argsort(y)]print(x_label)print(y)x_pos=np.arange(len(y))#设置每一个条形图的中心位置,要不没办法画图,条形图传数值型的x,y进去;同时也作为xticks的中心位置,这样就实现了用字符对x轴进行标plt.bar(x_pos,y)plt.xticks(x_pos,x_label,rotation=30)#xticks与xlabel是不一样,前者就跟刻度线一样的,后者只是说明x轴代表什么。plt.show()

结果如下:

这里写图片描述

转载地址:https://blog.csdn.net/qingqing7/article/details/78758746 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:编程基础---不同软件中的字符串操作
下一篇:数据基础---数据可视化

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月07日 21时30分47秒