【问题标题】:Copy values inside group with pyspark使用 pyspark 复制组内的值
【发布时间】:2021-10-28 20:24:48
【问题描述】:

我在 pyspark 中有一个与此类似的 df。我需要在组内复制值,而不留下空字符串。

+---------------+-----+----+
|values_to_copy |group|flag|
+---------------+-----+----+
|        value_1|   31|   1|
|               |   31|   1|
|        value_1|   31|   1|
|        value_2|  152|   1|
|               |  152|   1|
|               |  153|   1|
|        value_3|  153|   1|
|        value_4|  154|   1|
|               |  154|   1|
+---------------+-----+----+

我需要这样的输出。

+---------------+-----+----+
|values_to_copy |group|flag|
+---------------+-----+----+
|        value_1|   31|   1|
|        value_1|   31|   1|
|        value_1|   31|   1|
|        value_2|  152|   1|
|        value_2|  152|   1|
|        value_3|  153|   1|
|        value_3|  153|   1|
|        value_4|  154|   1|
|        value_4|  154|   1|
+---------------+-----+----+

我该怎么办?

【问题讨论】:

    标签: python dataframe pyspark


    【解决方案1】:

    如果你有这样的数据框:

    
    df = spark.createDataFrame((
        ("value_1", 31, 1),
        (None, 31, 1),
        ("value_1", 31, 1),
        ("value_2", 152, 1),
        (None, 152, 1),
        (None, 153, 1),
        ("value_3", 153, 1),
        ("value_4", 154, 1),
        (None, 154, 1),
    ),
        ("values_to_copy", "group", "flag"))
    
    df.show()
    
    # output
    +--------------+-----+----+
    |values_to_copy|group|flag|
    +--------------+-----+----+
    |       value_1|   31|   1|
    |          null|   31|   1|
    |       value_1|   31|   1|
    |       value_2|  152|   1|
    |          null|  152|   1|
    |          null|  153|   1|
    |       value_3|  153|   1|
    |       value_4|  154|   1|
    |          null|  154|   1|
    +--------------+-----+----+
    

    您首先需要定义要应用的窗口:

    from pyspark.sql import Window
    from pyspark.sql import functions as F
    
    w = Window().partitionBy("group").orderBy("group", F.desc("values_to_copy"))
    

    最后,您可以使用以下语法来实现您想要的:

    (
        df.withColumn("filled", 
                      F.first("values_to_copy", ignorenulls=True).over(w)
                     )
        .show()
    )
    
    # output
    +--------------+-----+----+-------+
    |values_to_copy|group|flag| filled|
    +--------------+-----+----+-------+
    |       value_1|   31|   1|value_1|
    |       value_1|   31|   1|value_1|
    |          null|   31|   1|value_1|
    |       value_3|  153|   1|value_3|
    |          null|  153|   1|value_3|
    |       value_4|  154|   1|value_4|
    |          null|  154|   1|value_4|
    |       value_2|  152|   1|value_2|
    |          null|  152|   1|value_2|
    +--------------+-----+----+-------+
    

    事实上,在此示例中,您可以使用 F.lastF.first 获得相同的结果,因为在每个组中,values_to_copy 列中只有一个值。

    因此,如果您有一个具有值的组:

    value_1
    value_1
    null
    

    当你使用F.first -> 你会得到value_1

    当你使用F.last -> 你会得到null,但由于参数ignorenulls=True 你会转到下一个值value_1

    当您在一个组中有几个不同的值时,就会出现差异,例如对于group=31,您将有values_to_copy

    value_2
    value_1
    value_1
    null
    

    这里F.first 将返回value_2 填充整个组,F.last 将返回value_1

    【讨论】:

    • ignorenulls=True 是天才 :)
    • 非常感谢它的工作。
    猜你喜欢
    • 2020-02-06
    • 1970-01-01
    • 2019-02-12
    • 2021-02-13
    • 1970-01-01
    • 2018-12-09
    • 2021-03-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多