当其他列具有第一个非缺失值时列的 pyspark 值

pyspark value of column when other column has first nonmissing value

假设我有以下 pyspark 数据框 df:

id     date   var1   var2
1         1   NULL      2
1         2      b      3
2         1      a   NULL
2         2      a      1

我想要所有 var* 列的第一个非缺失观察值以及它来自的日期值,即最终结果应该如下所示:

id     var1   dt_var1  var2    dt_var2
1         b         2     2          1  
2         a         1     1          2

使用

获取值很简单
df.orderBy(['id','date']).groupby('id').agg(
  *[F.first(x, ignorenulls=True).alias(x) for x in ['var1', 'var2']]
)

但我看不出如何获得相应的日期。我可以为变量循环变量,删除丢失的,并保留第一行。但这听起来像是一个糟糕的解决方案,无法很好地扩展,因为它需要为每个变量提供一个单独的数据框。

我更喜欢可扩展到多列的解决方案(var3var4、...)

如果您想根据日期顺序获得第一个 non-null,则不应使用 groupby。即使您之前调用了 orderby,也无法保证 groupby 操作后的顺序。

您需要改用 window 函数。要获取与每个 var 值关联的日期,您可以将此技巧与结构一起使用:

from pyspark.sql import Window, functions as F

w = (Window.partitionBy("id").orderBy("date")
     .rowsBetween(Window.unboundedPreceding, Window.unboundedFollowing)
     )

df1 = df.select(
    "id",
    *[F.first(
        F.when(F.col(x).isNotNull(), F.struct(x, F.col("date").alias(f"dt_{x}"))),
        ignorenulls=True).over(w).alias(x)
      for x in ["var1", "var2"]
      ]
).distinct().select("id", "var1.*", "var2.*")

df1.show()
#+---+----+-------+----+-------+
#| id|var1|dt_var1|var2|dt_var2|
#+---+----+-------+----+-------+
#|  1|   b|      2|   2|      1|
#|  2|   a|      1|   1|      2|
#+---+----+-------+----+-------+