2017-06-29 7 views
5

私は、複数の列があり、それらのうちのいくつかが構造体であるDataFrameを持っています。私はbazの機能をbazを置き換えるために、列bazUserDefinedFunctionを適用したいが、私はそれを行う方法を見つけ出すことはできません。このSpark SQL withColumnを入れ子にしました

root 
|-- foo: struct (nullable = true) 
| |-- bar: string (nullable = true) 
| |-- baz: string (nullable = true) 
|-- abc: array (nullable = true) 
| |-- element: struct (containsNull = true) 
| | |-- def: struct (nullable = true) 
| | | |-- a: string (nullable = true) 
| | | |-- b: integer (nullable = true) 
| | | |-- c: string (nullable = true) 

ような何か。ここでは所望の出力の一例であるDataFrame.withColumnのみネストした列の一番上のレベルの列に動作しますが、いないように見えます

root 
|-- foo: struct (nullable = true) 
| |-- bar: string (nullable = true) 
| |-- baz: int (nullable = true) 
|-- abc: array (nullable = true) 
| |-- element: struct (containsNull = true) 
| | |-- def: struct (nullable = true) 
| | | |-- a: string (nullable = true) 
| | | |-- b: integer (nullable = true) 
| | | |-- c: string (nullable = true) 

bazが今intであることに注意してください)。私はこの問題に対してScalaを使用しています。

誰かがこれで私を助けることができますか?簡単だ

おかげ

答えて

4

は、ちょうど例えば、ネストされた構造を選択するために、ドットを使用します$"foo.baz"

case class Foo(bar:String,baz:String) 
case class Record(foo:Foo) 

val df = Seq(
    Record(Foo("Hi","There")) 
).toDF() 


df.printSchema 

root 
|-- foo: struct (nullable = true) 
| |-- bar: string (nullable = true) 
| |-- baz: string (nullable = true) 


val myUDF = udf((s:String) => { 
// do something with s 
    s.toUpperCase 
}) 


df 
.withColumn("udfResult",myUDF($"foo.baz")) 
.show 

+----------+---------+ 
|  foo|udfResult| 
+----------+---------+ 
|[Hi,There]| THERE| 
+----------+---------+ 

あなたが得るために、既存の構造体fooにすなわちあなたのUDFの結果を追加したい場合は、次の

root 
|-- foo: struct (nullable = false) 
| |-- bar: string (nullable = true) 
| |-- baz: string (nullable = true) 
| |-- udfResult: string (nullable = true) 

2つのオプションがあります。withColumn

df 
.withColumn("udfResult",myUDF($"foo.baz")) 
.withColumn("foo",struct($"foo.*",$"udfResult")) 
.drop($"udfResult") 

select

df 
.select(struct($"foo.*",myUDF($"foo.baz").as("udfResult")).as("foo")) 

EDIT:UDFから結果を構造体に既存の属性を置き換える :残念ながら、これはありません ない作品:

df 
.withColumn("foo.baz",myUDF($"foo.baz")) 

が、このように行うことができます。

// get all columns except foo.baz 
val structCols = df.select($"foo.*") 
    .columns 
    .filter(_!="baz") 
    .map(name => col("foo."+name)) 

df.withColumn(
    "foo", 
    struct((structCols:+myUDF($"foo.baz").as("baz")):_*) 
) 
+0

これは正しい軌道にあると思いますが、理想的には、str内のすべての列名uct。 – Jon

+0

@Jon私の編集を参照 –

+0

これはうまくいくようですが、簡単にサブカラムの名前を置き換えることはできません。 – Jon

関連する問題