我试图强制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_sum
和feat_int_sum_temp
列,并将仅新数据部分追加到hdfs。
我将不胜感激有关如何强制spark仅将窗口函数应用于指定子集的提示,而实际窗口可以访问该子集之外的行。