数据基础---预处理---spark学习之数据预处理和特征提取

MovieLens数据集介绍

MovieLens 100k数据集,下载地址:http://files.grouplens.org/datasets/movielens/ml-100k.zip
MovieLens数据集保存了用户对电影的评分。基于这个数据集,我们可以测试一些推荐算法、评分预测算法。
MovieLens 100k
该数据集记录了943个用户对1682部电影的共100,000个评分,每个用户至少对20部电影进行了评分。
文件u.info保存了该数据集的概要:
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|85711
2|53|F|other|94043

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

user id | item id | rating | timestamp

具体如:

196	242	3	881250949
186	302	3	891717742
22	377	1	878887116
244	51	2	880606923
166	346	1	886397596
298	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:**其每一行的格式是:

<MovieID><Title><MoviePopularity>

MoviePopularity是在MovieLens中对该电影的评分次数。
**tag.dat:**每一行的格式是:

<TagID><Tag><TagPopularity>

是使用该Tag的用户数,一个用户最多算1次。
**tag_relevance.dat:**每一行的格式是:

<MovieID><TagID><Relevance>

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

数据探索

探索用户数据

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

#先载入数据
from pyspark import SparkConf,SparkContext
from pyspark.sql import SparkSession
sc=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 plt
import seaborn as sns
ages= 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()

结果如下:
这里写图片描述

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spark数据预处理是指在使用Spark进行数据分析之前对原始数据进行一系列的清洗、转换和整理操作。下面是一些常用的Spark数据预处理操作: 1. 导入Spark包:在开始之前,需要导入Spark相关的包,比如`from pyspark import SparkContext`。 2. 提交脚本:使用命令`spark-submit`来提交Spark脚本。 3. 导入数据:使用`sc.textFile()`函数导入数据,可以指定文件的路径和格式,比如`user_data = sc.textFile('/路径/ml-100k/u.user')`。 4. 查看数据:可以使用`first()`函数查看数据集中的某一条数据,比如`movie_data.first()`。 5. 字段处理:可以使用`map()`函数对每一行数据进行操作,比如将数据按照分隔符进行切割,生成字段。例如,`movie_fields = movie_data.map(lambda lines:lines.split('|'))`。 6. 数据转换:可以使用各种算子来对数据进行转换操作。常见的操作包括计数、加和、去重等。例如,`count()`函数用于计数和加和,`distinct()`函数用于去重,`collect()`函数用于将分散的内容整理成一个数组。 7. 典型问题分析:使用Spark进行数据预处理经常涉及到一些典型问题的分析,比如统计某一职业的人数。可以使用`map()`函数和`reduceByKey()`函数来实现。例如,`count_by_occupation = user_fields.map(lambda fields: (fields,1)).reduceByKey(lambda x,y:x+y).collect()`。 总之,Spark数据预处理是通过使用Spark的API和算子对原始数据进行清洗、转换和整理,为后续的数据分析提供规范化、可靠的数据集。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值