创建特定于数据帧的模式:以大写字母开头的StructField

时间:2019-12-02 15:39:04

标签: python pyspark schema azure-databricks pyspark-dataframes

为冗长的帖子表示歉意,看似简单,但我想提供完整的背景信息...

在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)

谢谢。

1 个答案:

答案 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