2016-12-04 20 views
11

DataFramefew columnsがあります。今、私は既存のDataFrameにさらに2つの列を追加したいと思います。withColumnを使用して既存のDataFrameに2つのカラムを追加する

現在、私はこれをDataFrameのwithColumnメソッドを使用して実行しています。例えば

df.withColumn("newColumn1", udf(col("somecolumn"))) 
    .withColumn("newColumn2", udf(col("somecolumn"))) 

実際に私は、配列[文字列]を使用して単一のUDF法の両方新たな列の値を返すことができます。しかし、現在、これは私がそれをやっている方法です。

とにかく、私はこれを効果的に行うことができますか? explodeを使用してここに良いオプションはありますか?

は私がexplodeを使用する必要がある場合でも、私はその後、一度withColumnを使用し、その後explodeを使用して、Array[String]として列の値を返し、さらに2つの列を作成する必要があります。

どちらが効果的ですか?または選択肢がありますか?

答えて

23

AFAIkを呼び出すには、withColumnを2回(新しい列ごとに1回)呼び出す必要があります。しかし、あなたのudfが計算上高価な場合は、 "複雑な"結果を一時的な列に格納して2回呼び出すことを避け、結果を "アンパック"します。 (配列の要素へのアクセスを与える)カラムのapply方法を使用して:

val myUDf = udf((s:String) => Array(s.toUpperCase(),s.toLowerCase())) 

val df = sc.parallelize(Seq("Peter","John")).toDF("name") 

val newDf = df 
    .withColumn("udfResult",myUDf(col("name"))) 
    .withColumn("uppercaseColumn", col("udfResult")(0)) 
    .withColumn("lowercaseColumn", col("udfResult")(1)) 
    .drop("udfResult") 

newDf.show() 

+-----+---------------+---------------+ 
| name|uppercaseColumn|lowercaseColumn| 
+-----+---------------+---------------+ 
|Peter|   PETER|   peter| 
| John|   JOHN|   john| 
+-----+---------------+---------------+ 

私はかなり頻繁にこれを行うが、アレイを使用してが、結果としてケースクラスまたはタプルを使用していないを与えますUDF

EDITから:

UDFはタプルを返すと、アンパックは次のようになります。

val newDf = df 
    .withColumn("udfResult",myUDf(col("name"))) 
    .withColumn("lowercaseColumn", col("udfResult._1")) 
    .withColumn("uppercaseColumn", col("udfResult._2")) 
    .drop("udfResult") 
+0

非常に興味深いアプローチです。あなたが得ることができる実際のパフォーマンスの利点を測定しましたか? –

+1

@AntonOkolnychyiもちろん、ユースケースによって異なります。私が計算するために〜500 milisecsを受け取り、出力の40列を生成UDFを持っています。この場合、私は絶対にこのUDFを複数回呼びたくはありません。 ..私は上記のパターン –

+0

@RaphaelRoth使用して:おかげで、どのように上記のケースのためのタプルを使用していますか?どのようにタプルの列から値を取得しますか?基本的にwithColumnsは値としてcol( "somecolumn")を受け入れます。 – Shankar

関連する問題