Python 更改spark dataframe列的架构

Python 更改spark dataframe列的架构,python,dataframe,apache-spark,pyspark,apache-spark-sql,Python,Dataframe,Apache Spark,Pyspark,Apache Spark Sql,我有一个pyspark数据框,列为“Student” 其中一项数据如下: { "Student" : { "m" : { "name" : {"s" : "john"}, "score": {"s" : "165"} } } } { "Student" : { "m" : { "StudentDetails" :

我有一个pyspark数据框,列为“Student”

其中一项数据如下:

{
   "Student" : {
       "m" : {
           "name" : {"s" : "john"},
           "score": {"s" : "165"}
       }
   }
}
{
    "Student" : 
    {
        "m" : 
        {
            "StudentDetails" : 
            {
                "m" : 
                {
                    "name" : {"s" : "john"},
                    "score": {"s" : "165"}
                }
            }
        }
    } 
}
我想更改此列的架构,使条目如下所示:

{
   "Student" : {
       "m" : {
           "name" : {"s" : "john"},
           "score": {"s" : "165"}
       }
   }
}
{
    "Student" : 
    {
        "m" : 
        {
            "StudentDetails" : 
            {
                "m" : 
                {
                    "name" : {"s" : "john"},
                    "score": {"s" : "165"}
                }
            }
        }
    } 
}
问题是,数据帧中的Student字段也可以为null。因此,我希望保留空值,但更改非空值的模式。我已经使用了一个udf用于上述过程,它是有效的

        def Helper_ChangeSchema(row):
            #null check
            if row is None:
                return None
            #change schema
            data = row.asDict(True)
            return {"m":{"StudentDetails":data}}
但udf是spark的黑匣子。是否有任何方法可以使用内置的spark函数或sql查询执行相同的操作。

其工作原理与中的完全相同。只需在结构中添加另一个嵌套级别:

作为SQL表达式:

processedDf=df.withColumn(“学生”,F.expr(“命名结构('m',命名结构('student\u details',student)))
或者在Python代码中使用:

processedDf=df.withColumn(“学生”),F.struct(F.struct(F.col(“学生”))。别名('m'))
两个版本的结果相同:

根目录
|--学生:struct(nullable=false)
||--m:struct(nullable=false)
|| |--student|u详细信息:struct(nullable=true)
|| | |--m:struct(nullable=true)
|| | | |--name:struct(nullable=true)
|| | | |--s:string(nullable=true)
|| | | |--score:struct(nullable=true)
|| | | |--s:string(nullable=true)
对于空行,这两种方法都可以很好地工作。使用此输入数据

data='{“student”:{“m”:{“name”:{“s”:“john”},“score”:{“s”:“165”}
data2='{“学生”:null}'
df=spark.read.json(sc.parallelize([data,data2]))
processedDf.show(truncate=False)
prints

+---------------------+
|学生|
+---------------------+
|[john][165][][165][]]|
|[[]]                 |
+---------------------+

编辑:如果整行应设置为null而不是结构的字段,则可以添加

processedDf=df.withColumn(“student”,F.when(F.col(“student”).isNull(),F.lit(None))。否则(F.struct(F.struct(F.col(“student”)。别名('m'))
这将导致相同的架构,但空行的输出不同:

+---------------------+
|学生|
+---------------------+
|[john][165][][165][]]|
|空的|
+---------------------+

问题有什么不同?{Student:null}也可以存在于数据中。答案有什么问题?为什么它不能与null一起工作?顺便说一句:你为什么不试试呢?是的,很酷的解决方案:)。但我正在努力应用这个函数,因为行可以为null,也可以为空。此解决方案将处理空行,但如何处理空行我认为空行工作正常。我已经添加了我的测试数据。