在数据框的子集上应用火花窗口功能

时间:2018-09-25 16:10:04

标签: apache-spark pyspark

我试图强制spark只在数据帧的指定子集上应用窗口函数,而实际窗口可以访问该子集之外的行。让我来看一个例子:

我有一个已经保存到hdfs的spark数据帧。数据帧包含事件,因此每一行都有一个时间戳,一个id和一个整数功能。还有一个我要计算的列,它是一个求和窗口函数,如下所示:

df = spark.table("some_table_in_hdfs")

w = Window.partitionBy("id").orderBy("date")
df = df.withColumn("feat_int_sum", F.sum("feat_int").over(w))

df.show()
+----------+--------+---+------------+
|      date|feat_int| id|feat_int_sum|
+----------+--------+---+------------+
|2018-08-10|       5|  0|           5|
|2018-08-12|      27|  0|          32|
|2018-08-14|       3|  0|          35|
|2018-08-11|      32|  1|          32|
|2018-08-12|     552|  1|         584|
|2018-08-16|       2|  1|         586|
+----------+--------+---+------------+

当我从其他来源加载新数据时,我想在hdfs中追加到上述数据帧。为此,我还必须将window函数也应用于新数据。我想合并两个数据框,以便窗口函数可以访问“旧” feat_int值来进行求和。

df_new = spark.table("some_new_table")
df_new.show()
+----------+--------+---+
|      date|feat_int| id|
+----------+--------+---+
|2018-08-20|      65|  0|
|2018-08-23|       3|  0|
|2018-08-24|       4|  0|
|2018-08-21|      69|  1|
|2018-08-25|      37|  1|
|2018-08-26|       3|  1|
+----------+--------+---+

df_union = df.union(df_new.withColumn("feat_int_sum", F.lit(None)))
df_union.show()
+----------+--------+---+------------+
|      date|feat_int| id|feat_int_sum|
+----------+--------+---+------------+
|2018-08-10|       5|  0|           5|
|2018-08-12|      27|  0|          32|
|2018-08-14|       3|  0|          35|
|2018-08-20|      65|  0|        null|
|2018-08-23|       3|  0|        null|
|2018-08-24|       4|  0|        null|
|2018-08-11|      32|  1|          32|
|2018-08-12|     552|  1|         584|
|2018-08-16|       2|  1|         586|
|2018-08-21|      69|  1|        null|
|2018-08-25|      37|  1|        null|
|2018-08-26|       3|  1|        null|
+----------+--------+---+------------+

问题是,我想将求和窗口函数应用于df_union,但仅应用于null中带有feat_int_sum的行。原因是我不想为df中已经计算的所有值重新计算窗口函数。因此所需的结果将是这样的:

+----------+--------+---+------------+-----------------+
|      date|feat_int| id|feat_int_sum|feat_int_sum_temp|
+----------+--------+---+------------+-----------------+
|2018-08-10|       5|  0|           5|             null|
|2018-08-12|      27|  0|          32|             null|
|2018-08-14|       3|  0|          35|             null|
|2018-08-20|      65|  0|        null|              100|
|2018-08-23|       3|  0|        null|              103|
|2018-08-24|       4|  0|        null|              107|
|2018-08-11|      32|  1|          32|             null|
|2018-08-12|     552|  1|         584|             null|
|2018-08-16|       2|  1|         586|             null|
|2018-08-21|      69|  1|        null|              655|
|2018-08-25|      37|  1|        null|              692|
|2018-08-26|       3|  1|        null|              695|
+----------+--------+---+------------+-----------------+

我尝试将window函数包装在when语句中,如下所示:

df_union.withColumn("feat_int_sum_temp", F.when(F.col('date') > '2018-08-16', F.sum('feat_int').over(w))

但是看看星火解释计划,似乎它将对所有行运行window函数,然后再应用when条件。 我不想在旧行上运行window函数的全部原因是我正在处理一些非常大的表,并且我不想浪费计算资源来重新计算将不会使用的值。 完成此步骤后,我将合并feat_int_sumfeat_int_sum_temp列,并将仅新数据部分追加到hdfs。 我将不胜感激有关如何强制spark仅将窗口函数应用于指定子集的提示,而实际窗口可以访问该子集之外的行。

0 个答案:

没有答案