Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark 从早期行累积数组(PySpark数据帧)_Apache Spark_Dataframe_Pyspark_Apache Spark Sql - Fatal编程技术网

Apache spark 从早期行累积数组(PySpark数据帧)

Apache spark 从早期行累积数组(PySpark数据帧),apache-spark,dataframe,pyspark,apache-spark-sql,Apache Spark,Dataframe,Pyspark,Apache Spark Sql,一个Python示例将使我的问题变得清晰。假设我有一个Spark数据框,其中有在特定日期观看特定电影的人,如下所示: root |-- name: string (nullable = true) |-- unixdate: long (nullable = true) |-- movies: array (nullable = true) | |-- element: string (containsNull = true) +-----+--------+----------

一个Python示例将使我的问题变得清晰。假设我有一个Spark数据框,其中有在特定日期观看特定电影的人,如下所示:

root
 |-- name: string (nullable = true)
 |-- unixdate: long (nullable = true)
 |-- movies: array (nullable = true)
 |    |-- element: string (containsNull = true)

+-----+--------+------------------+
|name |unixdate|movies            |
+-----+--------+------------------+
|Alice|1       |[Avatar]          |
|Bob  |2       |[Fargo, Tron]     |
|Alice|4       |[Babe]            |
|Alice|6       |[Avatar, Airplane]|
|Alice|7       |[Pulp Fiction]    |
|Bob  |9       |[Star Wars]       |
+-----+--------+------------------+
movierecord=spark.createDataFrame[Alice,1,[Avatar],Bob,2,[Fargo,Tron],Alice,4,[Babe],Alice,6,[Avatar,飞机],Alice,7,[低俗小说],Bob,9,[Star Wars]],[name,unixdate,movies] 上面定义的模式和数据帧如下所示:

root
 |-- name: string (nullable = true)
 |-- unixdate: long (nullable = true)
 |-- movies: array (nullable = true)
 |    |-- element: string (containsNull = true)

+-----+--------+------------------+
|name |unixdate|movies            |
+-----+--------+------------------+
|Alice|1       |[Avatar]          |
|Bob  |2       |[Fargo, Tron]     |
|Alice|4       |[Babe]            |
|Alice|6       |[Avatar, Airplane]|
|Alice|7       |[Pulp Fiction]    |
|Bob  |9       |[Star Wars]       |
+-----+--------+------------------+
我想从上面开始生成一个新的dataframe列,该列保存每个用户看到的所有以前的电影,在unixdate字段中没有重复的previous。所以它应该是这样的:

+-----+--------+------------------+------------------------+
|name |unixdate|movies            |previous_movies         |
+-----+--------+------------------+------------------------+
|Alice|1       |[Avatar]          |[]                      |
|Bob  |2       |[Fargo, Tron]     |[]                      |
|Alice|4       |[Babe]            |[Avatar]                |
|Alice|6       |[Avatar, Airplane]|[Avatar, Babe]          |
|Alice|7       |[Pulp Fiction]    |[Avatar, Babe, Airplane]|
|Bob  |9       |[Star Wars]       |[Fargo, Tron]           |
+-----+--------+------------------+------------------------+
如何以一种非常高效的方式实现这一点?

仅SQL而不保留对象的顺序:

所需进口:

导入pyspark.sql.f函数 从pyspark.sql.window导入窗口 窗口定义:

w=Window.partitionByname.orderByunixdate 完整解决方案:

电影录影带 压平电影 上一部电影,f 收集独一无二的 .使用列Previous_movies,f.collect_setprevious_movie.over 删除单个unixdate的重复项 .groupByname,unixdate .aggf.maxf.struct f、 前几部电影, f、 colmovies.Alias电影, f、 colprevious_movies.alias previous_movies .tmp 按1移位并提取 选择 名称、unixdate、tmp.movies、, f、 lagtmp.previous_电影,1.Over.Alias previous_电影 结果是:

+---+----+---------+------------+ |名称| unixdate |电影|之前的|电影| +---+----+---------+------------+ |鲍勃| 2 |[法戈,特隆]|空| |鲍勃| 9 |[星球大战][法戈,特隆]| |爱丽丝| 1 |[阿凡达]|空| |爱丽丝| 4 |[宝贝]|[阿凡达]| |爱丽丝| 6 |[阿凡达,飞机]|[宝贝,阿凡达]| |爱丽丝| 7 |[低俗小说]|[宝贝,飞机,阿凡达]| +---+----+---------+------------+ SQL是保留顺序的Python UDF:

进口:

导入pyspark.sql.f函数 从pyspark.sql.window导入窗口 从pyspark.sql导入列 从pyspark.sql.types导入ArrayType、StringType 从输入导入列表中,输入Union https://github.com/pytoolz/toolz 从toolz导入唯一、concat、compose UDF:

def展平\u distinctcol:Union[列,str]->列: def flant_distinctxss:Union[List[List[str]],None]>List[str]: 返回composelist、unique、concatxss或[] 返回f.udfflaten\u distinct\u,ArrayTypeStringTypecol 窗口定义与以前一样

完整解决方案:

电影录影带 收集清单 .在前几部电影的专栏中,f.收集前几部电影 展平并删除重复项 .使用前几部电影,将前几部电影的内容展平 一班 .带专栏的前几部电影,f.Lag前几部电影,1.Over 仅供演示 .orderByunixdate 结果是:

+---+----+---------+------------+ |名称| unixdate |电影|之前的|电影| +---+----+---------+------------+ |爱丽丝| 1 |[阿凡达]|空| |鲍勃| 2 |[法戈,特隆]|空| |爱丽丝| 4 |[宝贝]|[阿凡达]| |爱丽丝| 6 |[阿凡达,飞机]|[阿凡达,宝贝]| |爱丽丝| 7 |[低俗小说]|[阿凡达,宝贝,飞机]| |鲍勃| 9 |[星球大战][法戈,特隆]| +---+----+---------+------------+ 性能:

我认为,鉴于这些限制,没有有效的方法来解决这一问题。不仅请求的输出需要大量的数据复制数据是二进制编码的,以适应钨格式,因此您可以获得可能的压缩,但对象标识松散,而且还可以获得许多操作,这些操作在给定的Spark计算模型中非常昂贵,包括昂贵的分组和排序

若之前电影的预期大小有限且很小,但通常不可行,那个么这应该是好的

通过为用户保留单一的惰性历史记录,数据复制非常容易解决。这不是用SQL可以完成的事情,但是使用低级RDD操作非常容易

爆炸和收集模式是昂贵的。如果您的要求很严格,但希望提高性能,那么可以使用Scala UDF代替Python UDF