2017-02-19 6 views
1
scala> val df = spark.read.json("data.json") 

scala> df.printSchema 
root 
|-- a: struct (nullable = true) 
| |-- b: struct (nullable = true) 
| | |-- c: long (nullable = true) 
|-- **TimeStamp: string (nullable = true)** 
|-- id: string (nullable = true) 


scala> val df1 = df.withColumn("TimeStamp", $"TimeStamp".cast(TimestampType)) 

scala> df1.printSchema 
root 
|-- a: struct (nullable = true) 
| |-- b: struct (nullable = true) 
| | |-- c: long (nullable = true) 
|-- **TimeStamp: timestamp (nullable = true)** // WORKING AS EXPECTED 
|-- id: string (nullable = true) 


scala> val df2 = df.withColumn("a.b.c", $"a.b.c".cast(DoubleType)) 

scala> df2.printSchema 
root 
|-- a: struct (nullable = true) 
| |-- b: struct (nullable = true) 
| | |-- c: long (nullable = true) 
|-- TimeStamp: string (nullable = true) 
|-- id: string (nullable = true) 
|-- **a.b.c: double (nullable = true)** // DUPLICATE COLUMN ADDED 

データフレームの列内にネストされたJSON属性のタイプを変更しようとしています。ネストされた属性の変更は新しい列として扱われ、重複する列が作成されます。変更はトップレベルの属性(タイムスタンプ)では正しく動作していますが、ネストされたもの(a.b.c)では正しく動作していません。この問題に関する考えは?ネストされたJSON属性のタイプを変更する

答えて

1

あなたの列は構造体型&であるため、同じ階層で再度作成する必要があります。それは仮定ではないので、あなたは構造を書き直していると思います。 入力:私はそれが明らかであると思います

root 
|-- TimeStamp: string (nullable = true) 
|-- a: struct (nullable = true) 
| |-- b: struct (nullable = true) 
| | |-- c: string (nullable = true) 
| | |-- d: string (nullable = true) 
|-- id: long (nullable = true) 

root 
|-- TimeStamp: date (nullable = true) 
|-- a: struct (nullable = false) 
| |-- b: struct (nullable = false) 
| | |-- c: double (nullable = true) 
| | |-- d: string (nullable = true) 
|-- id: long (nullable = true) 

{"a": {"b": {"c": "1.31", "d": "1.11"}}, "TimeStamp": "2017-02-18", "id":1} 
{"a": {"b": {"c": "2.31", "d": "2.22"}}, "TimeStamp": "2017-02-18", "id":1} 

val lines2 = spark.read.json("/home/kiran/km/km_hadoop/data/data_nested_struct_col2.json") 
lines2.printSchema() 

val df2 = lines2.withColumn("a", struct(
            struct(
             lines2("a.b.c").cast(DoubleType).as("c"), 
             lines2("a.b.d").as("d") 
            ).as("b"))) 
      .withColumn("TimeStamp", lines2("TimeStamp").cast(DateType)) 
df2.printSchema() 

これは後に&前に両方のスキーマの出力です。

+0

あなたのコードは何ですか? – KiranM

+0

私はa - > b - > cのために同じ階層を使って構築しようとしました。できます。しかし、これは、ツリー内の同じレベルに1つの属性がある場合にのみ機能するようです。 a - > b - > cとa - > b - > dの2つの属性がある場合、a - > b - > dは削除され、a - > b - > b - > c。これはうまくいかないかもしれません。 – Kris

+0

あなたは1つのことを無視していますが、この解決策は、DataframeのwithColumn()関数内でドット表記を使用して内部列を呼び出す方法がないという制限(少なくとも私が知っている限り)に基づいています。これは作業する列名の単純な文字列を受け入れます。したがって、スケーラブルではない同じ構造を維持する必要があります。元の構造が異なる場合、コードも変更されます。コメントセクションは書式設定を許可しないため、修正されたコードを新しい回答として追加します... – KiranM

関連する問題