Python PySpark:对象的长度与字段的长度不匹配-正在创建新架构

Python PySpark:对象的长度与字段的长度不匹配-正在创建新架构,python,apache-spark,Python,Apache Spark,我目前正在使用AWS Glue和PySpark。我正在尝试手动创建Spark模式,并将其应用于dataframe,以解决我在某些列中遇到的一些问题 我当前的问题是struct类型的列。我的数据在通过Glue读取的JSON中只有6个字段,但将来可能有8个字段。如果我用目前为止收到的6个字段构建模式,效果很好,但是如果我用应该得到的8个字段构建模式,我会得到以下错误:ValueError:field name_struct:object的长度(6)与字段的长度(8)不匹配 应用更新的模式的最佳方式是

我目前正在使用AWS Glue和PySpark。我正在尝试手动创建Spark模式,并将其应用于dataframe,以解决我在某些列中遇到的一些问题

我当前的问题是struct类型的列。我的数据在通过Glue读取的JSON中只有6个字段,但将来可能有8个字段。如果我用目前为止收到的6个字段构建模式,效果很好,但是如果我用应该得到的8个字段构建模式,我会得到以下错误:ValueError:field name_struct:object的长度(6)与字段的长度(8)不匹配

应用更新的模式的最佳方式是什么?我认为我应该对我的struct列应用一个函数,并使用null值创建缺少的键,以便在数据中包含预期的8个键。你知道怎么做吗?如果这样做,我认为对于所有struct类型的列,我应该解析模式,比较列中的数据(asDict()?)和模式之间的键,最后添加缺少的键。我觉得有更好的方法来处理Spark或者一些我还没有找到的参数,以便在创建数据帧时自动修复它们

import findspark

findspark.init()

import pyspark
from pyspark.sql import SparkSession
from pyspark.sql.types import StringType, IntegerType, StructType, StructField

spark = SparkSession.builder.master("local[1]") \
                .appName('test_schema') \
                .getOrCreate()
                
data = [
    (32, ("James", "Smith"), ("street", 42)),
    (18, ("Nina", "Smith"), ("street 2", 12))
]

schema = StructType([
    StructField('age', IntegerType(), True),
    StructField('name_struct', StructType([
        StructField('first_name', StringType(), True),
        StructField('last_name', StringType(), True)
    ])),
    StructField('address_struct', StructType([
        StructField('street', StringType(), True),
        StructField('number', IntegerType(), True)
    ]))
])

df = spark.createDataFrame(data=data, schema=schema)
df.printSchema()
df.show()

schema2 = StructType([
    StructField('age', IntegerType(), True),
    StructField('name_struct', StructType([
        StructField('first_name', StringType(), True),
        StructField('last_name', StringType(), True),
        StructField('middle_name', StringType(), True)
    ])),
    StructField('address_struct', StructType([
        StructField('street', StringType(), True),
        StructField('number', IntegerType(), True),
        StructField('zip_code', IntegerType(), True)
    ]))
])

# fix data here?

df2 = spark.createDataFrame(data=data, schema=schema2)
# error here:  ValueError: field name_struct: Length of object (2) does not match with length of fields (3)
df2.printSchema()
df2.show()

谢谢

你知道你的输入JSON模式会多久改变一次吗?@AchyutVyas事实上,不。它不应该经常改变,但我希望解决方案足够通用,ETL可以毫无错误地处理它。之后我会展平嵌套字段,不管值是否为null,但键必须在那里,否则下一个进程将缺少列。我目前正在尝试UDF并从structtype中提取字段名,但这感觉像是一种黑客行为。你知道你的输入JSON模式会多长时间更改一次吗?@AchyutVyas事实上,不是。它不应该更改为“经常”,但我希望解决方案足够通用,ETL可以毫无错误地处理它。之后我会展平嵌套字段,不管值是否为null,但键必须在那里,否则下一个进程将缺少列。我目前正在尝试UDF并从structtype中提取字段名,但感觉像是一个黑客。