通过检查另一行pyspark的条件来更新特定行中的值

qcuzuvrc  于 2021-07-13  发布在  Spark
关注(0)|答案(2)|浏览(377)

所以我试了一堆东西,但都没用。请参见Dataframe。
测向
indexboolnew\u bool1true2true3true4false真
我想更新一列( New_bool ). 它应该包含false if列 Bool 已经是false,并且它的行中也应该包含false index=1 如果 Bool 与…排成一行 index=4 也是假的。所有其他行应保持原样。我无法做到这一点…请看下面的预期输出。
IndexBool1TrueFalse2True3False4FalseFalse索引
我尝试了不同的。when语句组合,但没有成功。迄今为止最好的解决方案:

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

但这会产生:
IndexBool1TrueNone2TrueNone3TrueNone4FalseFalse索引
如果我现在能用中第4行的值填充所有的none New_Bool 我想那会有帮助的。然后,我又建立了另一个专栏:

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

因为我尝试了太多的组合,所以我不再确定什么了……顺便说一句,我将有许多组Dataframe,这就是为什么我需要一个与groupby或窗口函数一起工作的解决方案。
乐于接受每一个建议:)

lymnna71

lymnna711#

您还可以选择最后一个索引的 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|

# +-----+-----+--------+
s8vozzvw

s8vozzvw2#

你可以用 lead 当index=1时检查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|
+-----+-----+--------+

另一种方法是交叉连接到索引为4的行的bool:

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'))
)

相关问题