为冗长的帖子表示歉意,看似简单,但我想提供完整的背景信息...
在Databricks中,我将基于特定的架构定义创建数据“行”,然后将该行插入到空数据框中(也基于相同的特定架构)。
模式定义如下:
myschema_xb = StructType(
[
StructField("_xmlns", StringType(), True),
StructField("_Version", DoubleType(), True),
StructField("MyIds",
ArrayType(
StructType(
[
StructField("_ID", StringType(), True),
StructField("_ID_Context", StringType(), True),
StructField("_Type", LongType(), True),
]
),
True
),
True
),
]
)
行条目因此是:
myRow = Row(
_xmlns="http://some.where.com",
_Version=12.3,
MyIds=[
Row(
_ID="XY",
_ID_Context="Exxwhy",
_Type=9
),
Row(
_ID="9152",
_ID_Context="LNUMB",
_Type=21
),
]
)
最后,databricks笔记本代码为:
mydf = spark.createDataFrame(sc.emptyRDD(), myschema_xb)
rows = [myRow]
rdf = spark.createDataFrame(rows, myschema_xb)
appended = mydf.union(rdf)
对rdf = spark.createDataFrame(rows, myschema_xb)
的调用导致异常:
ValueError: Unexpected tuple 'h' with StructType
。
现在我很想知道的部分是,如果我将元素MyIds
更改为myIds
(即首字母小写),代码起作用和我的新数据框(appended
)具有单行数据。
此异常是什么意思?为什么在更改元素大小写时会消失?
(仅供参考,我们的databricks运行时环境为Scala 2.11)
谢谢。
答案 0 :(得分:0)
问题应该出在documentation中,Row对象如何对键/字段进行排序:
行可被用于通过使用命名的参数创建一个行对象,字段将通过名称进行排序。
在myschema_xb
中,三列按[_xmlns, _Version, MyIds]
的顺序定义。当使用键(_xmlns, _Version, MyIds)
定义myRow时,生成的实际Row对象将是:
Row(MyIds=[Row(_ID='XY', _ID_Context='Exxwhy', _Type=9), Row(_ID='9152', _ID_Context='LNUMB', _Type=21)], _Version=12.3, _xmlns='http://some.where.com')
MyIds
已移至第一列,而这与架构不匹配,因此会产生错误。当您使用小写的列名myIds
时,Row对象中的键按['_Version', '_xmlns', 'myIds']
排序,其中右列中有myIds
,但是_Version
和{{1} }切换。这不会产生错误,因为简单的数据类型可以通过类型转换进行传递,但是结果数据帧不正确。
要解决此问题,您应该设置一个类似Row的类并自定义键的顺序,以确保字段的顺序与模式中显示的顺序完全匹配:
_xmls