[英]Keep null values as null in PySpark dense_rank()
我正在嘗試根據包含空值的列在分區內進行排序。
這個 DataFrame 可以創建如下:
df = spark.createDataFrame(
[("2019-01-01", 5),
("2019-01-01", 20),
("2019-01-01", 10),
("2019-01-03", 1),
("2019-01-03", None),
("2019-01-03", None),
("2019-01-03", 2),
("2019-01-05", 10)],
("Date", "value")
)
看起來像:
+----------+-----+
| Date|value|
+----------+-----+
|2019-01-01| 5|
|2019-01-01| 20|
|2019-01-01| 10|
|2019-01-03| 1|
|2019-01-03| null|
|2019-01-03| null|
|2019-01-03| 2|
|2019-01-05| 10|
+----------+-----+
現在我想將每個日期的每個值從 1 到N
進行排名。 我嘗試使用以下代碼:
w = Window.partitionBy("date").orderBy("value")
df = df.withColumn("rank", F.dense_rank().over(w))
但是,這顯然將所有null
值列為 1,而不管列中有多少null
值:
+----------+-----+----+
| Date|value|rank|
+----------+-----+----+
|2019-01-03| null| 1|
|2019-01-03| null| 1|
|2019-01-03| 1| 2|
|2019-01-03| 2| 3|
|2019-01-05| 10| 1|
|2019-01-01| 5| 1|
|2019-01-01| 10| 2|
|2019-01-01| 20| 3|
+----------+-----+----+
如何更改dense_rank()
的行為,使其在排名時將null
值保持在null
,而不是給這些值任意排名 1?
您所需要的只是一個以分區和實際排名為條件的isNull()
。 不幸的是,不能直接在pyspark
中修改dense_rank()
。 代碼如下所示:
from pyspark.sql import Window
common_condition = f.col("value").isNull()
w = Window.partitionBy(
f.col('Date'),
f.when(common_condition, 1).otherwise(0)
).orderBy(f.col("value"))
df = df.withColumn(
"rank",
f.when(common_condition, f.lit(None)).otherwise(f.dense_rank().over(w))
)
df.show()
+----------+-----+----+
| Date|value|rank|
+----------+-----+----+
|2019-01-03| 1| 1|
|2019-01-03| 2| 2|
|2019-01-03| null|null|
|2019-01-03| null|null|
|2019-01-05| 10| 1|
|2019-01-01| 5| 1|
|2019-01-01| 10| 2|
|2019-01-01| 20| 3|
+----------+-----+----+
或者,您可以使用pyspark.sql.functions.desc_nulls_last()
並隨后過濾掉f.col("value").isNull()
和您的排名列f.col("rank")
等於分區的位置f.max()
但這可能更笨重,更難閱讀。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.