2016-10-21 2 views
2

したがって、xmlファイルからdataframeを作成しています。それはディーラーに関するいくつかの情報を持っているし、ディーラーは複数の車を持っています - 各車はcars要素のサブ要素であり、value要素で表されます - 各cars.value要素にはさまざまな車属性があります。だから私は、次のようにディーラーのためにそれぞれの車に1つの行を作成するためにexplode機能を使用します。データフレームに存在しない列を選択する

exploded_dealer = df.select('dealer_id',explode('cars.value').alias('a_car')) 

を、今私がcars.value

のさまざまな属性を取得したい私はこのようにそれを行う:

car_details_df = exploded_dealer.select('dealer_id','a_car.attribute1','a_car.attribute2') 

これは問題なく動作します。しかし、時にはcars.value要素に、私のクエリで指定したすべての属性が含まれていないことがあります。だから、例えば、いくつかの要素がcars.valueのみattribute1のがあるかもしれない - と、上記のコードの実行時に、私は次のエラーが発生します。

pyspark.sql.utils.AnalysisException:u」が解決できない与えられた 『attribute2の』 を入力列:[dealer_id、attribute1]; "

どのように私はsparkにとにかく同じクエリを実行するように頼むのですか? の属性2の場合は、Noneを返してください。

initial_file_df = sqlContext.read.format('com.databricks.spark.xml').options(rowTag='dealer').load('<xml file location>') 

exploded_dealer = df.select('financial_data',explode('cars.value').alias('a_car')) 
+0

これは、Pythonコードではなく失敗したSQLクエリであるため、これは難しいです。私が驚いているのは、通常、データフレーム用に1つのスキーマがあり、このスキーマには属性を含めることができるかどうかということです。だからバグか、データセットを構築するのに手間がかかっていました。はいの場合は、指定してください。とにかく、興味深いのは、Spark SQLでTRYに相当するものがないということです。つまり、データフレームの作成時にすべての属性を持つスキーマを強制するなど、回避策を使用する必要があります。 – Wilmerton

+0

「通常、データフレーム用に1つのスキーマがあるのは驚きです」 - つまり、私のコードは静的なので、ファイルから列a、b、cを常に取るように指定できます。そこにあり、私はそれらの3つの列だけが必要です。しかし、ある日には列a、b、dのxmlがあるかもしれませんが、c列のデータが得られない場合でも、まだa、b、cのみが必要です。私のコードは静的なので、a、b、cを求め、cが足りないので失敗するでしょう。 – Dennis

+0

@Dennis私はそれがあなたの質問に対する答えではないことを知っていますが、それにもかかわらず助けになるかもしれません:まず、スキーマを取得し、それに応じてクエリを生成するロジックを作ることができます。 – Wilmerton

答えて

1

あなたはすでにあなたができる最善のことはnullableオプションのフィールドで明示的に定義し、データをインポートするときに、それを使用することで、スキーマについての具体的な仮定をしているので、次のよう

UPDATE私は自分のデータを読み取ります。

のは、あなたがに類似した文書を期待しましょう:

<rows> 
    <row> 
     <id>1</id> 
     <objects> 
      <object> 
       <attribute1>...</attribute1> 
       ... 
       <attributebN>...</attributeN> 
      </object> 
     </objects> 
    </row> 
</rows> 

attribute1attribute2を、...、attributebNは、所与のバッチに存在しない可能性がありますが、選択肢とそれに対応するタイプの有限集合を定義することができます。

{("attribute1", StringType), ("attribute2", LongType)} 

あなたのようにスキーマを定義することができます:

schema = StructType([ 
    StructField("objects", StructType([ 
    StructField("object", StructType([ 
     StructField("attribute1", StringType(), True), 
     StructField("attribute2", LongType(), True) 
    ]), True) 
    ]), True), 
    StructField("id", LongType(), True) 
]) 

と読者とそれを使用します。簡単にするための2つだけのオプションがあるとしましょう

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

それは、任意のサブセットのために有効になります({∅、{属性1}、{属性2}、{属性1、属性2}})のうちの1つである。同時に、スキーマの推論に依存するより効率的です。

関連する問題