【问题标题】:Fill NaN with group-by other column in spark用 spark 中的 group-by 其他列填充 NaN
【发布时间】:2021-03-26 12:39:36
【问题描述】:

数据

 Col1 Col2    result
0  a    x      123.0 
1  a    y     NaN    
2  a    x      453.0 
3  a    y      675.0 
4  b    z      786.0 
5  b    z      332.0 

我想用 675.0 填充 NaN,首先按 col1 分组,然后按 col2 并填充 NaN 值

在熊猫中

df['result'] = df['result'].fillna(df.groupby(['col1', 'col2', ])['result'].bfill())


df['result'] = df['result'].fillna(df.groupby(['col1', 'col2', ])['result'].ffill())

如何在 pyspark 中实现它?

【问题讨论】:

    标签: python apache-spark pyspark apache-spark-sql


    【解决方案1】:

    这可以通过pandas udfs 完成。然后就可以直接使用你想要的功能了。

    [IN]
    from pyspark.sql.functions import pandas_udf, PandasUDFType
    import pandas as pd, numpy as np
    
    s = pd.DataFrame({"col1": ["a","a","a","a","b","b"],
                  "col2": ["x", "y", "x", "y", "z", "z"],
                  "result": [123, np.nan, 453, 675, 786, 332]})
    
    spark_df = spark.createDataFrame(s)
    
    grouped_spark_df = spark_df.groupBy("col1", "col2")
    
    @pandas_udf("col1 string, col2 string, result float", PandasUDFType.GROUPED_MAP)
    def fillnaspark(df):
        df['result'] = df['result'].bfill()
        df['result'] = df['result'].ffill()
        return df
    
    grouped_spark_df.apply(fillnaspark).show()
    
    [OUT]
    +----+----+------+
    |col1|col2|result|
    +----+----+------+
    |   a|   x| 123.0|
    |   a|   x| 453.0|
    |   b|   z| 786.0|
    |   b|   z| 332.0|
    |   a|   y| 675.0|
    |   a|   y| 675.0|
    +----+----+------+
    

    【讨论】:

      【解决方案2】:

      您可以使用nanvlNaN 替换为结果的lead 值(等效于ffillbfill 将是lag):

      from pyspark.sql import functions as F, Window
      
      df2 = df.withColumn(
          'id', F.monotonically_increasing_id()
      ).withColumn(
          'result', 
          F.nanvl(
              'result',
              F.coalesce(
                  F.lag('result').over(Window.partitionBy('Col1', 'Col2').orderBy('id')),
                  F.lead('result').over(Window.partitionBy('Col1', 'Col2').orderBy('id'))
              )
          )
      ).orderBy('id')
      
      df2.show()
      +---+----+----+------+
      | id|Col1|Col2|result|
      +---+----+----+------+
      |  0|   a|   x| 123.0|
      |  1|   a|   y| 675.0|
      |  2|   a|   x| 453.0|
      |  3|   a|   y| 675.0|
      |  4|   b|   x| 786.0|
      |  5|   b|   y| 332.0|
      +---+----+----+------+
      

      【讨论】:

      • `AnalysisException: cannot resolve 'id' given input columns:`
      • 哦,我没有意识到id 不是一个专栏。您可以尝试修改后的解决方案。
      • 这里有问题,缺失值的数量应该从 589,784 减少到 374,323,但是使用此代码它增加到 3,354,901
      • 我看不到你的数据,所以我怕我不知道哪里出了问题。如果您能提供一些相关的示例数据来解释您的问题,那就太好了。
      • 那你为什么要过滤条件(df["result"] == "")
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-20
      • 1970-01-01
      • 2017-03-11
      • 2020-11-14
      • 1970-01-01
      相关资源
      最近更新 更多