【问题标题】:update value in specific row by checking condition for another row, pyspark通过检查另一行的条件来更新特定行中的值,pyspark
【发布时间】:2021-02-22 21:18:53
【问题描述】:

所以我尝试了很多东西,但似乎没有任何效果。 查看数据框。

df

index Bool New_Bool
1 True True
2 True True
3 True True
4 False True

我想更新一个列 (New_bool)。如果列Bool 已经为假,则它应该包含假,并且如果Bool 行中的index=4 也为假,它也应该包含假与index=1。所有其他行应保持原样。我无法做到这一点...请参阅下面的预期输出。

index Bool New_Bool
1 True False
2 True True
3 False False
4 False False

我尝试了 .when 语句的不同组合,但没有奏效。迄今为止最好的解决方案:

df = df.withColumn('New_Bool', F.when((F.col('index')==4) &
                               ((F.col('Bool')==False), False))

但这会产生:

index Bool New_Bool
1 True None
2 True None
3 True None
4 False False

如果我现在能够用New_Bool 中第 4 行的值填充所有无值,那我猜这会有所帮助。然后我会设置另一个最后一列:

df = df.withColumn('Final_Bool', F.when((F.col('index')==1) &
                               ((F.col('New_Bool')==False), False).otherwise(F.col('Bool'))

虽然我对任何事情都不确定,因为我尝试了这么多组合....顺便说一下,我将拥有许多组这些数据帧,这就是为什么我需要一个与 groupby 或窗口函数一起使用的解决方案。

对每一个建议都很满意 :)

【问题讨论】:

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


    【解决方案1】:

    您也可以将最后一个索引的Bool 值选择到一个变量中,并在如下表达式中使用它:

    from pyspark.sql import functions as F
    
    # or actually, if the index is always = 4 you can just filter without ordering
    last_bool = df.orderBy(F.desc("index")).limit(1).select("Bool").first().Bool
    
    df2 = df.withColumn(
        'New_Bool',
        F.when(
            F.col('index') == 1, 
            F.lit(last_bool) & F.col("New_bool") # keep New_bool or update to false if last is false  
        ).otherwise(
            F.col("New_bool") & F.col("Bool") # keep New_bool or update to false if Bool is false 
        )
    )
    
    df2.show()
    # +-----+-----+--------+
    # |index| Bool|New_Bool|
    # +-----+-----+--------+
    # |    1| true|   false|
    # |    2| true|    true|
    # |    3|false|   false|
    # |    4|false|   false|
    # +-----+-----+--------+
    

    【讨论】:

      【解决方案2】:

      当 index = 1 时,您可以使用lead 来检查 index = 4 的行。对于其他索引,只需保留 bool 列即可。

      from pyspark.sql import functions as F, Window
      
      df2 = df.withColumn(
          'New_Bool',
          F.when(
              (F.col('index') == 1) & 
              (F.lead('Bool', 3).over(Window.orderBy('index')) == False),
              False
          ).otherwise(F.col('Bool'))
      )
      
      df2.show()
      +-----+-----+--------+
      |index| Bool|New_Bool|
      +-----+-----+--------+
      |    1| true|   false|
      |    2| true|    true|
      |    3|false|   false|
      |    4|false|   false|
      +-----+-----+--------+
      

      另一种方法是对 index = 4 的行的布尔值进行交叉连接:

      df2 = df.crossJoin(
          df.filter('index = 4')
            .select(F.col('Bool').alias('id_4'))
      ).withColumn(
          'New_Bool',
          F.when(
              (F.col('index') == 1) & (F.col('id_4') == False), 
              False
          ).otherwise(F.col('Bool'))
      ).drop('id_4')
      

      如果 4 始终是最后一个索引,那么您可以使用last

      df2 = df.withColumn(
          'New_Bool',
          F.when(
              (F.col('index') == 1) & 
              (F.last('Bool').over(Window.orderBy('index').rowsBetween(Window.unboundedPreceding, Window.unboundedFollowing)) == False),
              False
          ).otherwise(F.col('Bool'))
      )
      

      【讨论】:

      • 感谢您的快速响应!第一个解决方案对我不起作用,因为索引 4 不一定距离索引 1 3 步(例如,df 可能缺少索引 2)。不过,4 永远是最后一个。没有使用“last”的窗口函数,是吗?解决方案 2 可能对我有用。我会试试。再次感谢:)
      • @Bondgirl 有一个last 窗口函数!请参阅我编辑的答案。这应该是你最好的选择。
      • 现在我很困惑,我尝试使用您的方法: df2 = df.withColumn( 'New_Bool', F.when( (F.col('index') == 1) & (F.last('Bool').over(Window.orderBy('index')) == False), False ).otherwise(F.col('Bool')) ) 但这只会复制 Bool 列并且'不更新第一个索引,不知道我做错了什么,如果它对你有用 使用 last_bool 的解决方案给了我一个错误,我无法真正确定,因为我正在使用 databricks-connect 并且对所有这些东西都很陌生:o) ...射击...
      • @Bondgirl 啊,我忘了指定窗框。更新的答案应该可以正常工作。让我知道这是否适合你
      • @mck 非常感谢!即使在我为我的组添加了另一个 partitionby 之后,它也能正常工作:o)!
      猜你喜欢
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-31
      • 2012-06-19
      • 2016-08-22
      • 1970-01-01
      相关资源
      最近更新 更多