Pyspark RDD到具有强制架构的数据帧:值错误

Pyspark RDD到具有强制架构的数据帧:值错误,pyspark,schema,rdd,Pyspark,Schema,Rdd,我正在使用pyspark,其模式与本文末尾所示的模式(注意嵌套列表、无序字段)相当,最初作为数据帧从Parquet导入。从根本上说,我遇到的问题是无法将此数据作为RDD处理,然后转换回数据帧。(我已经看了好几篇相关的文章,但我仍然不知道我错在哪里。) 简单地说,以下代码工作正常(正如人们所期望的): 当我需要映射RDD时,事情就不起作用了(例如,添加字段就是这样) 上面的代码给出了以下例外情况,其中XXX是整数的替代,在不同的运行中会发生变化(例如,我看到了1、16、23等): 根据这些信息,第

我正在使用pyspark,其模式与本文末尾所示的模式(注意嵌套列表、无序字段)相当,最初作为数据帧从Parquet导入。从根本上说,我遇到的问题是无法将此数据作为RDD处理,然后转换回数据帧。(我已经看了好几篇相关的文章,但我仍然不知道我错在哪里。)

简单地说,以下代码工作正常(正如人们所期望的):

当我需要映射RDD时,事情就不起作用了(例如,添加字段就是这样)

上面的代码给出了以下例外情况,其中XXX是整数的替代,在不同的运行中会发生变化(例如,我看到了1、16、23等):

根据这些信息,第二个代码块中是否存在明显错误?(我注意到tripRDD属于rdd.rdd类,而tripRDDNew属于rdd.PipelinedRDD类,但我认为这不应该是一个问题。)(我还注意到tripRDD的模式不是按字段名排序的,而tripRDDNew的模式是按字段名排序的。同样,我不明白这是一个问题。)

模式:

root
 |-- foo: struct (nullable = true)
 |    |-- bar_1: integer (nullable = true)
 |    |-- bar_2: integer (nullable = true)
 |    |-- bar_3: array (nullable = true)
 |    |    |-- element: struct (containsNull = true)
 |    |    |    |-- baz_1: integer (nullable = true)
 |    |    |    |-- baz_2: string (nullable = true)
 |    |    |    |-- baz_3: double (nullable = true)
 |    |-- bar_4: array (nullable = true)
 |    |    |-- element: struct (containsNull = true)
 |    |    |    |-- baz_1: integer (nullable = true)
 |    |    |    |-- baz_2: string (nullable = true)
 |    |    |    |-- baz_3: double (nullable = true)
 |-- qux: integer (nullable = true)
 |-- corge: integer (nullable = true)
 |-- uier: integer (nullable = true)`

正如文章中提到的,原始模式中的字段不是按字母顺序排列的。这就是问题所在。在映射函数中使用.asDict()对结果RDD的字段进行排序。tripRDDNew的字段顺序与调用createDataFrame时的架构冲突。ValueError是由于试图将其中一个整数字段(即示例中的qux、corge或uier)解析为StructType而导致的

(顺便说一句:createDataFrame要求模式字段的顺序与RDD字段的顺序相同,这有点令人惊讶。您应该需要一致的字段名或一致的字段顺序,但要求两者似乎有些过分。)

(另一方面:数据帧中非字母字段的存在有些反常。例如,sc.parallelize()将在分发数据结构时自动按字母顺序排列字段。从拼花地板文件导入数据帧时,似乎应该对字段进行排序。研究一下为什么不是这样可能会很有趣。)

schema = deepcopy(tripDF.schema)
tripRDD = tripDF.rdd
def trivial_map(row):
    rowDict = row.asDict()
    return pyspark.Row(**rowDict)
tripRDDNew = tripRDD.map(lambda row: trivial_map(row))
tripDFNew = sqlContext.createDataFrame(tripRDDNew, schema)
tripDFNew.take(1)
File "/opt/cloudera/parcels/CDH-5.8.3-
1.cdh5.8.3.p1967.2057/lib/spark/python/pyspark/sql/types.py", line 546, in 
toInternal
raise ValueError("Unexpected tuple %r with StructType" % obj)
ValueError: Unexpected tuple XXX with StructType`
root
 |-- foo: struct (nullable = true)
 |    |-- bar_1: integer (nullable = true)
 |    |-- bar_2: integer (nullable = true)
 |    |-- bar_3: array (nullable = true)
 |    |    |-- element: struct (containsNull = true)
 |    |    |    |-- baz_1: integer (nullable = true)
 |    |    |    |-- baz_2: string (nullable = true)
 |    |    |    |-- baz_3: double (nullable = true)
 |    |-- bar_4: array (nullable = true)
 |    |    |-- element: struct (containsNull = true)
 |    |    |    |-- baz_1: integer (nullable = true)
 |    |    |    |-- baz_2: string (nullable = true)
 |    |    |    |-- baz_3: double (nullable = true)
 |-- qux: integer (nullable = true)
 |-- corge: integer (nullable = true)
 |-- uier: integer (nullable = true)`