【问题标题】:How to modify pyspark dataframe nested struct column如何修改pyspark数据框嵌套结构列
【发布时间】:2022-01-07 15:15:49
【问题描述】:

我正在尝试匿名化/散列嵌套列,但没有成功。架构看起来像这样:

-- abc: struct (nullable = true)
|    |-- xyz: struct (nullable = true)
|    |    |-- abc123: string (nullable = true)
|    |    |-- services: struct (nullable = true)
|    |    |    |-- service: array (nullable = true)
|    |    |    |    |-- element: struct (containsNull = true)
|    |    |    |    |    |-- type: string (nullable = true)
|    |    |    |    |    |-- subtype: string (nullable = true)

我需要更改(匿名化/散列)type 列的值。

【问题讨论】:

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


    【解决方案1】:

    对于 Spark 3.1+,有一个列方法withField 可用于更新结构字段。

    假设这是您的输入数据框(对应于您提供的架构):

    from pyspark.sql import Row
    
    df = spark.createDataFrame([
        Row(abc=Row(xyz=Row(abc123="value123", services=[Row(type="type1", subtype="subtype1")])))
    ])
    
    df.show(truncate=False)
    #+---------------------------------+
    #|abc                              |
    #+---------------------------------+
    #|{{value123, [{type1, subtype1}]}}|
    #+---------------------------------+
    

    您可以在数组services 上使用transform 对每个结构元素的字段type 进行哈希处理(这里我使用xxhash64 函数来说明),如下所示:

    import pyspark.sql.functions as F
    
    df2 = df.withColumn(
        "abc",
        F.col("abc").withField(
            "xyz",
            F.col("abc.xyz").withField(
                "services",
                F.expr("transform(abc.xyz.services, x -> struct(xxhash64(x.type) as type, x.subtype))")
            )
        )
    )
    
    df2.show(truncate=False)
    #+-----------------------------------------------+
    #|abc                                            |
    #+-----------------------------------------------+
    #|{{value123, [{2134479862461603894, subtype1}]}}|
    #+-----------------------------------------------+
    

    对于较旧的 Spark 版本,您需要重新创建整个结构以更新字段,这使得嵌套字段很多时变得乏味。在你的情况下,它会是这样的:

    df2 = df.withColumn(
        "abc",
        F.struct(
            F.struct(
                F.col("abc.xyz.abc123"),
                F.expr(
                    "transform(abc.xyz.services, x -> struct(xxhash64(x.type) as type, x.subtype))"
                ).alias("services")
            ).alias("xyz")
        )
    )
    

    【讨论】:

      猜你喜欢
      • 2018-07-24
      • 1970-01-01
      • 1970-01-01
      • 2021-08-26
      • 2021-12-08
      • 2018-07-21
      • 2021-12-29
      • 2018-01-31
      • 2020-12-07
      相关资源
      最近更新 更多