2017-11-23 13 views
0

私は多くの列を持つスパークデータフレームを持っています。今、それらをマップに組み合わせて新しい列を作成したいと思います。例: しかし、私はまだdatasetにdfを変換する必要がありスパークデータフレーム列をマップ列に埋め込む方法は?

df.withColumn("newcol", struct(df.columns.head, df.columns.tail: _*)) 

:これを行うには

col1:String col2:String col3:String... coln:String => 
col: Map(colname -> colval) 

一つの方法は、にあります。 structタイプと一致するケースクラスを定義する方法はわかりません。

もう1つの選択肢は、マップタイプに列を埋め込むことですが、これを表現する方法はわかりません。

+0

データフレームにいくつの行がありますか? –

+0

約40、それを一つずつリストアップするのは非常に面倒です – user3162587

+1

質問が分かりません。 'Map(colname - > colval)' 'colval'は' colname'の下のすべての値の配列であるべきですか?そして、あなたが提供した方法は、各行を構造体として取得します。あなたが上で説明したものと全く同じではありません。サンプルデータセットと必要な出力を詳しく教えてください。 – philantrovert

答えて

1

既存のすべての列から新しい列を作成する場合は、ここで簡単な解決策の1つがあります。パフォーマンス上の理由から

import org.apache.spark.sql.functions._ 
val columnsName = ds.columns 
val mkMap = udf((values: mutable.WrappedArray[Int]) => columnsName.zip(values).toMap) 
ds.withColumn("new_col", mkMap(array(columnsName.head, columnsName.tail:_*))) 
1

、あなたは既存スパーク機能を使用して、独自のUDFを転がり回避できます

org.apache.spark.sql.functions.map 

ここでは完全に例を働いている:中

var mydata = Seq(("a", "b", "c"), ("d", "e", "f"), ("g", "h", "i")) 
       .toDF("f1", "f2", "f3") 

var colnms = mydata.columns.map(lit(_)) 
var colvals = mydata.columns.map(col(_)) 
var colnms_n_vals = colnms.zip(colvals).flatMap{ case (a,b) => Array(a,b) } 

display(mydata.withColumn("myMap", map(colnms_n_vals:_*))) 

結果これは:

f1 f2 f3 myMap 
a b c {"f1":"a","f2":"b","f3":"c"} 
d e f {"f1":"d","f2":"e","f3":"f"} 
g h i {"f1":"g","f2":"h","f3":"i"} 
+0

(Spark APIドキュメントのとおり)すべての列が同じデータ型で動作する必要があることに注意してください。 – Chondrops

関連する問題