【问题标题】:creating dataframe specific schema : StructField starting with capital letter创建数据框特定模式:以大写字母开头的 StructField
【发布时间】:2020-03-27 06:16:21
【问题描述】:

对于看似简单的好奇心,对于冗长的帖子表示歉意,但我想提供完整的上下文......

在 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 notebook 代码是:

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(即第一个字母小写),代码 works,以及我的新数据框(@ 987654328@) 有单行数据。

这个异常是什么意思?为什么当我更改元素的大小写时它会消失?

(仅供参考,我们的 databricks 运行时环境是 Scala 2.11)

谢谢。

【问题讨论】:

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


    【解决方案1】:

    问题应该出自 Row 对象如何对键/字段进行排序,来自documentation

    Row 可用于使用命名参数创建行对象,字段将按名称排序。

    myschema_xb 中,三列按[_xmlns, _Version, MyIds] 的顺序定义。当您使用键定义 myRow 时:(_xmlns, _Version, MyIds),实际生成的 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_xmls 切换。这不会产生错误,因为简单数据类型可以通过类型转换,但生成的数据帧不正确。

    要解决这个问题,您应该设置一个类似 Row 的类并自定义键的顺序,以确保字段的顺序与您的架构中显示的完全匹配:

    from pyspark.sql import Row
    
    MyOuterROW = Row('_xmlns', '_Version', 'MyIds')
    MyInnerRow = Row('_ID', '_ID_Context', '_Type')
    
    myRow = MyOuterROW( 
        "http://some.where.com", 
        12.3, 
        [ 
            MyInnerROW("XY", "Exxwhy", 9), 
            MyInnerROW("9152", "LNUMB", 21) 
        ] 
    )              
    print(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)])
    
    rdf = spark.createDataFrame([myRow], schema=myschema_xb)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-26
      • 2015-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      • 2012-01-14
      • 1970-01-01
      相关资源
      最近更新 更多