Apache spark 选择数据框中不存在的列

Apache spark 选择数据框中不存在的列,apache-spark,pyspark,apache-spark-sql,Apache Spark,Pyspark,Apache Spark Sql,因此,我从一个XML文件创建了一个dataframe。它有一些关于经销商的信息,然后经销商有多辆车-每辆车都是cars元素的子元素,由value元素表示-每辆cars.value元素都有不同的车属性。因此,我使用explode函数为经销商的每辆车创建一行,如下所示: exploded\u dealer=df.select('dealer\u id',exploded('cars.value')。别名('a\u car')) 现在我想获得汽车的各种属性。value 我是这样做的: car\u d

因此,我从一个XML文件创建了一个
dataframe
。它有一些关于经销商的信息,然后经销商有多辆车-每辆车都是
cars
元素的子元素,由
value
元素表示-每辆
cars.value
元素都有不同的车属性。因此,我使用
explode
函数为经销商的每辆车创建一行,如下所示:

exploded\u dealer=df.select('dealer\u id',exploded('cars.value')。别名('a\u car'))
现在我想获得
汽车的各种属性。value

我是这样做的:

car\u details\u df=分解的经销商。选择('dealer\u id'、'a\u car.attribute1'、'a\u car.attribute2')
这很好。但是有时候
cars.value
元素没有我在查询中指定的所有属性。例如,一些
cars.value
元素可能只有attribute1-然后在运行上述代码时,我将得到以下错误:

pyspark.sql.utils.AnalysisException:u“无法解析'attribute2' 给定输入列:[经销商id,属性1];”

我如何要求Spark执行相同的查询。但是如果属性2不存在,只需返回
None

更新我读取的数据如下:

initial_file_df=sqlContext.read.format('com.databricks.spark.xml')。选项(rowTag='dealer')。加载(“”)
分解经销商=df.select('financial_data',分解('cars.value')。别名('a_car'))

既然您已经对模式做出了特定的假设,那么最好的办法就是使用
可空
可选字段显式定义它,并在导入数据时使用它

假设您希望文档类似于:

<rows>
    <row>
        <id>1</id>
        <objects>
            <object>
                <attribute1>...</attribute1>
                 ...
                <attributebN>...</attributeN>
            </object>
        </objects>
    </row>
</rows>
您可以将架构定义为:

schema = StructType([
  StructField("objects", StructType([
    StructField("object", StructType([
      StructField("attribute1", StringType(), True),
      StructField("attribute2", LongType(), True)
    ]), True)
  ]), True),
  StructField("id", LongType(), True)
])
并与reader一起使用:

spark.read.schema(schema).option("rowTag", "row").format("xml").load(...)

它对属性的任何子集都有效({∅, {attribute1},{attribute2},{attribute1,attribute2})。同时比依赖模式推断更有效。

这很棘手,因为失败的是SQL查询,而不是python代码。让我惊讶的是,通常一个数据帧有一个模式,这个模式可以包含属性,也可以不包含属性。所以要么它是一个bug,要么你做了一些棘手的事情来构建你的数据集。如果是,请具体说明。无论如何,有趣的是,我认为在sparksql中没有类似的TRY。这意味着您必须使用一种变通方法,比如在创建数据帧时强制使用具有所有属性的模式。“让我惊讶的是,通常一个数据帧只有一个模式”-所以问题是:我的代码是静态的,所以我可以指定始终从文件中获取列a、b、c,因为我知道他们在那里,我只需要那三列。但有一天可能会有一个包含a、b、d列的xml—但我仍然只需要a、b、c列,即使这意味着我没有获得c列的数据。因为我的代码是静态的,它会要求a、b、c,而且因为c缺失,它会失败。@Dennis我知道这不是你问题的答案,但它可能会有所帮助:你可以先做一个逻辑,得到模式,然后相应地生成查询。
spark.read.schema(schema).option("rowTag", "row").format("xml").load(...)