当其他列具有第一个非缺失值时列的 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']]
)
但我看不出如何获得相应的日期。我可以为变量循环变量,删除丢失的,并保留第一行。但这听起来像是一个糟糕的解决方案,无法很好地扩展,因为它需要为每个变量提供一个单独的数据框。
我更喜欢可扩展到多列的解决方案(var3
、var4
、...)
如果您想根据日期顺序获得第一个 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|
#+---+----+-------+----+-------+
假设我有以下 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']]
)
但我看不出如何获得相应的日期。我可以为变量循环变量,删除丢失的,并保留第一行。但这听起来像是一个糟糕的解决方案,无法很好地扩展,因为它需要为每个变量提供一个单独的数据框。
我更喜欢可扩展到多列的解决方案(var3
、var4
、...)
如果您想根据日期顺序获得第一个 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|
#+---+----+-------+----+-------+