pyspark 实现混合推荐_数据

Photo by SpaceX on Unsplash

每个数据分析师都应该熟悉的重要主题之一是分布式数据处理技术(例如Spark)。作为数据分析师,需要对数据集应用不同的查询,以从数据集中提取有用的信息。 

但是,如果您的数据很庞大以至于无法在本地计算机上使用它,该怎么办? 

使用分布式数据处理和Spark技术将很方便解决这个问题。Apache Spark是用于大数据处理的快速通用引擎,它具有用于流,SQL,机器学习和图处理的内置模块。它以其速度,易用性,通用性以及几乎可以在任何地方运行的能力而闻名。

数据科学家可通过Spark,对大批量数据进行探索性数据分析,特征提取,机器学习和模型评估。

在分布式数据处理中,将数据分为较小部分称为 RDD,并分别处理每个部分。这样,我们可以更快地运行查询。

下面将通过一个小项目,入门使用Spark进行数据探索分析,并实现以下目标:

  • 学会使用pySpark模块;
  • 了解如何在数据集中,通过不同的查询以提取有用的信息;
  • 了解如何在pySpark下使用matplotlib可视化;

-  读取数据 -

本文将使用 lastfm 网站公开的数据集,使用 pySpark 进行一些查询和探索。该网站是一种在线音乐服务,用户可以在其中收听不同的音乐歌曲。该数据集包含两个csv文件listen.csv和genre.csv。

下面导入 pySpark 模块:

from pyspark.sql import SparkSessionfrom pyspark.sql.functions import count, desc , col, max, structimport matplotlib.pyplot as plts

读取 CSV 数据集:

listening_csv_path="/dataset/listenings.csv"listening_df = spark.read.format('csv').option('inferSchema', True).option('header', True).load(listening_csv_path)

因为此处加载的 CSV 文件的文件大小为 1 GB,可能需要一些时间。上面这行代码将返回一个 pySpark 的 DataFrame,并将其存储在 listening_df 中。

-  查看数据基本信息 -

首先可以查看下数据内容:

listening_df.show()

pyspark 实现混合推荐_pyspark udf 多个参数_02

show() 默认最多显示20 条数据。listening_df 是属于 pySpark 的 DataFrame。pySpark 的 DataFrame 和pandas 的 DataFrame 是不同的,它们之间有很多差异。

下面可以删除数据集中无用的列,这里date列是没有用的:

listening_df = listening_df.drop('date')

接下来,我要删除内部具有空值的那些行。可以这样做:

br

我们可以检查下上面操作的结果:

listening_df.show()

pyspark 实现混合推荐_数据集_03

可以看到空值和 date 列均被删除。

在操作 DataFrame 前,查看数据集中列的数据类型是很重要的。可以使用printSchema 查看:

listening_df.printSchema()

pyspark 实现混合推荐_数据集_04

让我们再看看 DataFrame 中有多少行和列:

shape = (listening_df.count(), len(listening_df.columns))print(shape)

pyspark 实现混合推荐_数据_05

因为 pySpark 的 DataFrame 没有 shape 属性,想要查看它的行和列数,并不像 pandas 的 DataFrame 那样简单。


-  探索分析数据 -


现在将开始做些查询操作,以提取数据集中有用的信息。这里会从简单的开始直到更高级的查询。下面以几个查询任务来介绍这一块。


Q0 :查看关注的某些列数据,而不是全部列数据


可使用 select 。例如,只想查出 track 和 artist的数据: 

q0 = listening_df.select('track', 'artist')q0.show()

pyspark 实现混合推荐_数据集_06


Q1 :查找听过 Rihanna 的用户的所有记录


用filter可以进行条件过滤:

q1 = listening_df.select('*').filter(listening_df.album == 'Rihanna')q1.show()

pyspark 实现混合推荐_数据集_07

其中,select中的 * 和 SQL 中的 * 作用相同,都是查询出所有的列。


Q2 :找到对 Rihanna 感兴趣的 TOP 10 用户


这个查询稍微复杂些。因此,为了查询出结果,必须首先过滤出听过 rihanna的所有用户。然后根据用户进行汇总以计算用户收听 Rihanna 的次数。最后进行降序排序,并取出 top 10 的用户。

q2 = listening_df.select('user_id').filter(listening_df.artist=='Rihanna').groupby("user_id").agg(count("user_id").alias("count")).orderBy(desc("count")).limit(10)q2.show()

pyspark 实现混合推荐_数据_08


Q3 :找出最受欢迎的 TOP 10 歌曲


这个跟 Q2 的类似,都是需要汇总统计和排序。需要注意的一点是,在分组时不能只是以歌曲进行分组汇总统计,而是需要将歌手和歌曲一起进行分组汇总。因为歌曲存在重名的情况。

所以这里主要关注多列分组的用法。

q3 = listening_df.select('artist', 'track').groupby('artist', 'track').agg(count("*").alias("count")).orderBy(desc("count")).limit(10)q3.show()

pyspark 实现混合推荐_pyspark udf 多个参数_09


Q4 :找出 Rihanna 最受欢迎的 TOP 10 歌曲


此查询与上一个Q3查询基本一样,只不过要加一个过滤条件就可以了。

q4 =listening_df.select('artist', 'track').filter(listening_df.artist == 'Rihanna').groupby("artist", "track").agg(count("*").alias("count")).orderBy(desc("count")).limit(10)q4.show()

pyspark 实现混合推荐_数据_10

-  合并数据 -

本模块主要介绍pySpark中合并数据的方法,会涉及到不同来源的数据集。所以下面,会导入第二份数据集, 此数据集包含歌手的曲风类型(简称:流派)数据:

genre_csv_path = "/dataset/genre.csv"genre_df = spark.read.format('csv').option("inferSchema",True).option("header", True).load(genre_csv_path)genre_df.show()

pyspark 实现混合推荐_pyspark 实现混合推荐_11

可以看到此数据集只包含歌手名 artist 和对应的流派 genre。下面将两个数据集进行合并。

使用 join 方法, 参数 how 指定要合并的方式。on 指定合并时的主键,可以是一个列,也可以是多个列。

data = listening_df.join(genre_df, how='inner', on=['artist'])data.show()

pyspark 实现混合推荐_spark_12

可以看到流派genre被合并了进来。

   -  复杂查询 -

合并数据后,做一个复杂查询吧. 


Q5 .查找 top10 流派


q5 = data.select("genre").groupby("genre").agg(count("*").alias("count")).orderBy(desc("count")).limit(10)q5.show()

pyspark 实现混合推荐_pyspark 实现混合推荐_13


Q6. 找出每个用户最喜欢的流派


因此,我们要做的就是为每个用户找到他或她喜欢的类型。或者说她或他喜欢什么类型的音乐。

这个查询有点复杂,因此下面将分为两部分进行查询操作。

首先,计算每个用户收听特定流派的次数,然后我们会发现他或她听过很多次或最多次的流派。

q6_1 = data.select("user_id", 'genre').groupby("user_id","genre").agg(count("*").alias("count"))q6_1.show()

pyspark 实现混合推荐_pyspark 实现混合推荐_14

下面,我将找出每个用户听过最大次数的流派:

q8_2 = q8_1.groupby("user_id").agg(max(struct('count', 'genre')).alias("max")).select("user_id", "max.genre", "max.count")q8_2.show()

pyspark 实现混合推荐_spark_15

可以看到已经成功输出要查询的结果。

这里需要注意max的使用和select的使用:

# max(struct('count', 'genre'))# select("user_id", "max.genre", "max.count")

用到了struct函数,struct函数将允许您将两个或多个列组合在一起。所以这里使用了一个技巧,在使用max找到最大值时,也可以返回流派名称。

 -  数据可视化 -

现在让我们继续进行最后的可视化操作。我们需要找出有多少摇滚(rock),流行(pop),金属乐(metal)和嘻哈(hip hop)的歌手,然后要使用条形图将其可视化。

所以先需要统计出这些流派的歌手数:

q7.show()

pyspark 实现混合推荐_数据集_16

然后构造数据并进行可视化:

labels = [row["genre"] for row in q7_list]counts = [row["count"] for row in q7_list]plts.bar(labels, counts)

pyspark 实现混合推荐_数据_17

另一种可视化的方法是,可以把 pySpark 的DataFrame 转化成 pandas 的DataFrame,然后进行可视化。

pySpark 提供了 to_pandas() 方法,可以方便的进行转换。

- End -

参考及示例:

http://spark.apache.org/docs/latest/sql-programming-guide.html

https://www.coursera.org/projects/data-analysis-using-pyspark

to_pandas():

http://spark.apache.org/docs/latest/sql-pyspark-pandas-with-arrow.html

数据集:

http://millionsongdataset.com/