【问题标题】:Is there a way to guess the schema dynamically in Pyspark?有没有办法在 Pyspark 中动态猜测模式?
【发布时间】:2021-11-23 17:55:18
【问题描述】:

我在 Databricks 中有一个表,其中有一列作为字符串字典,如下所示 -

+---+--------------------------------------------------------------------------------------------------------------+
|id |stringDictionary                                                                                              |
+---+--------------------------------------------------------------------------------------------------------------+
|abc|{"col1": "someValue", "col2" : "someValue", "col3" : "someValue"}                                             |
|def|{"col1" : "someValue", "col3": "someValue"}                                                                   |
|mnp|{"col1" : "someValue", "col2" : "someValue", "col3" : "someValue", "col4" : "someValue", "col5" : "someValue"}|
|abc|{"col4" : "someValue", "col5" : "someValue", "col6" : "someValue"}                                            |
+---+--------------------------------------------------------------------------------------------------------------+

现在每个 id 都可以有多个结构,如图所示。

我尝试为其中几个定义 Struct 架构,如下所示 -

from pyspark.sql.types import StructType,StructField, StringType
from pyspark.sql.functions import col,from_json

schema = StructType([ 
    StructField("col1",StringType(),True), 
    StructField("col2",StringType(),True), 
    StructField("col3",StringType(),True), 
    StructField("col4", StringType(), True)
  ])

dfJSON = sparkDF.withColumn("jsonData",from_json(col("stringDictionary"),schema)) \
                   .select("stringDictionary","jsonData.*","*")#.drop("stringDictionary")

display(dfJSON)

但这不是一个好方法,因为每次添加新元素时都不够用,必须手动更改架构。

有没有办法处理所有此类情况或在读取此表或数据帧时猜测结构架构并将其对应的stringDictionary 展平为自己的单独列?

请帮忙。

【问题讨论】:

    标签: python arrays python-3.x apache-spark pyspark


    【解决方案1】:

    使用以下代码将 sparkDF 的 stringDictionary 列转换为 MapType -

    from pyspark.sql.functions import *
    from pyspark.sql.types import *
    
    df = (sparkDF.withColumn("cols", 
                              from_json( col("stringDictionary"), 
                                         MapType(StringType(), StringType())
                                        )
                             )
                 .drop("stringDictionary")
           )
    

    现在,cols 列需要分解如下 -

    df2 = df.select("id", explode("cols").alias("col_columns", "col_rows"))
    
    display(df2)
    

    一旦您将 col_columnscol_rows 作为单独的列,我们需要做的就是旋转 col_columns 并使用其对应的 col_rows 聚合它,如下所示 -

    df3 = df2.groupBy("id")
             .pivot("col_columns")
             .agg(first("col_rows"))
    
    display(df3)
    
    

    【讨论】:

      【解决方案2】:

      使用schema_of_json() 动态创建架构,然后使用MergeSchema 进行架构演进。

      请注意,在生产环境中,有时 json 有效负载可能会以错误的数据类型发送。此外,模式演化不适用于嵌套结构。

      【讨论】:

      • schema_of_json 如果我直接传递 stringDictionary due to data type mismatch: The input json should be a foldable string expression and not null 会抛出错误
      • 等等,这列真的是字符串吗?因为不应该给出这个错误
      • 是的,确实如此
      • 您不能将任何字符串列传递给schema_of_json 方法,它必须是可折叠的列(大致意思是由lit 创建或lit 列的转换)。您可以查看my answerWhy schema_of_json fails? 问题了解更多详情。还有What is a foldable column ?问题
      猜你喜欢
      • 1970-01-01
      • 2011-12-17
      • 2017-08-20
      • 1970-01-01
      • 1970-01-01
      • 2021-09-11
      • 2018-06-23
      • 2020-09-27
      • 1970-01-01
      相关资源
      最近更新 更多