【问题标题】:replace NA with median in pyspark using window function使用窗口函数将 NA 替换为 pyspark 中的中位数
【发布时间】:2020-02-26 07:10:06
【问题描述】:

我想在 pyspark 中使用窗口函数根据分区列将 NA 替换为 medain?

示例输入:

所需输出:

【问题讨论】:

  • 在所需的输出中,您的 p_id 的最后一个值应该是 5,这样中位数可以计算为 2,否则它不会落在分区中,我已经在我的解决方案中进行了更改,发布很快
  • 是的,你是对的,5 不是 2

标签: python apache-spark pyspark window


【解决方案1】:

创建您的数据框:

list=([1,5,4],
    [1,5,None],
    [1,5,1],
    [1,5,4],
    [2,5,1],
    [2,5,2],
    [2,5,None],
    [2,5,None],
     [2,5,4])
df=spark.createDataFrame(list,['I_id','p_id','xyz'])
df.show()

+----+----+----+
|I_id|p_id| xyz|
+----+----+----+
|   1|   5|   4|
|   1|   5|null|
|   1|   5|   1|
|   1|   5|   4|
|   2|   5|   1|
|   2|   5|   2|
|   2|   5|null|
|   2|   5|null|
|   2|   5|   4|
+----+----+----+

为了使解决方案尽可能通用和动态,我必须创建许多新列来计算中位数,并能够将其发送到空值。话虽如此,解决方案不会很慢,并且可以针对大数据进行扩展。

from pyspark.sql.window import Window
from pyspark.sql import functions as F
from pyspark.sql.functions import when
w= Window().partitionBy("I_id","p_id").orderBy(F.col("xyz").asc_nulls_first())
w2= Window().partitionBy("I_id","p_id")
df.withColumn("xyz1",F.count(F.col("xyz").isNotNull()).over(w))\
.withColumn("xyz2", F.max(F.row_number().over(w)).over(w2))\
.withColumn("xyz3", F.first("xyz1").over(w))\
.withColumn("xyz10", F.col("xyz2")-F.col("xyz3"))\
.withColumn("xyz9", F.when((F.col("xyz2")-F.col("xyz3"))%2!=0, F.col("xyz2")-F.col("xyz3")+1).otherwise(F.col("xyz2")-F.col("xyz3")))\
.withColumn("xyz4", (F.col("xyz9")/2))\
.withColumn("xyz6", F.col("xyz4")+F.col("xyz3"))\
.withColumn("xyz7", F.when(F.col("xyz10")%2==0,(F.col("xyz4")+F.col("xyz3")+1)).otherwise(F.lit(None)))\
.withColumn("xyz5", F.row_number().over(w))\
.withColumn("medianr", F.when(F.col("xyz6")==F.col("xyz5"), F.col("xyz")).when(F.col("xyz7")==F.col("xyz5"),F.col("xyz")).otherwise(F.lit(None)))\
.withColumn("medianr2", (F.mean("medianr").over(w2)))\
.withColumn("xyz", F.when(F.col("xyz").isNull(), F.col("medianr2")).otherwise(F.col("xyz")))\
.select("I_id","p_id","xyz")\
.orderBy("I_id").show()

+----+----+---+
|I_id|p_id|xyz|
+----+----+---+
|   1|   5|  4|
|   1|   5|  1|
|   1|   5|  4|
|   1|   5|  4|
|   2|   5|  2|
|   2|   5|  2|
|   2|   5|  1|
|   2|   5|  2|
|   2|   5|  4|
+----+----+---+

【讨论】:

  • 我们能用 aprroximatequantile 找到近似中位数吗?
  • 如果您想要整个列的中位数为 1,您可以使用它。 Approxquantile 不是聚合函数,因此您将无法为您的用例放置一个窗口。 @VigneshwarThiyagarajan
  • @murtihash,我试图理解您提供的答案,并且对理解您编写的 windows 功能有一些疑问。我在另一篇文章中编译了这个,stackoverflow.com/questions/66927213/… 你想看一下吗?谢谢。
猜你喜欢
  • 2020-06-08
  • 1970-01-01
  • 2019-08-16
  • 2016-05-10
  • 2016-09-09
  • 1970-01-01
  • 2015-10-29
  • 1970-01-01
相关资源
最近更新 更多