2017-03-07 6 views
1

ScalaのDataFrameに値を転置する際に問題が発生しています。 DataFrame私の初期には、次のようになります。Spark:データフレームにUDFを適用するDFの値に基づいて新しい列を生成する

+----+----+----+----+ 
|col1|col2|col3|col4| 
+----+----+----+----+ 
| A| X| 6|null| 
| B| Z|null| 5| 
| C| Y| 4|null| 
+----+----+----+----+ 

col1col2はタイプStringcol3あるとcol4Intです。

そして結果は次のようになります。3つの新しい列がcol1col2と値が抽出されている列にちなんで命名されなければならないことを意味

+----+----+----+----+------+------+------+ 
|col1|col2|col3|col4|AXcol3|BZcol4|CYcol4| 
+----+----+----+----+------+------+------+ 
| A| X| 6|null|  6| null| null| 
| B| Z|null| 5| null|  5| null| 
| C| Y| 4| 4| null| null|  4| 
+----+----+----+----+------+------+------+ 

。抽出された値は、nullではない値に応じて、col2col3またはcol5の列から取得されます。

どのように達成するには?私が最初にこのようなUDF考える:

def myFunc (col1:String, col2:String, col3:Long, col4:Long) : (newColumn:String, rowValue:Long) = { 
    if col3 == null{ 
     val rowValue=col4; 
     val newColumn=col1+col2+"col4"; 
    } else{ 
     val rowValue=col3; 
     val newColumn=col1+col2+"col3"; 
    } 
    return (newColumn, rowValue); 
} 

val udfMyFunc = udf(myFunc _) //needed to treat it as partially applied function 

しかし、どのように私は正しい方法でデータフレームからそれを呼び出すことができますか?

もちろん、上記のコードはすべてゴミであり、はるかに良い方法があるかもしれません。私はちょうど最初のコードスニペットをゆがんでいるので、私に知らせてください... Intの値をnullに比較することは、既に機能していません。

ご協力いただきましてありがとうございます。ありがとう!

+0

[Apache Spark - 複数のデータフレーム列にUDFの結果を割り当てる]可能な複製(http://stackoverflow.com/questions/35322764/apache-spark-assign-the-result-of-udf-to- – jwvh

答えて

0

わかりました。私が望むことを達成するための回避策があります。私は、次の操作を行います

(1)私はこのアドバイスDerive multiple columns from a single column in a Spark DataFrame

case class toTuple(newColumnName: String, rowValue: String) 

def createTuple (input1:String, input2:String) : toTuple = { 
    //do something fancy here 
    var column:String= input1 + input2 
    var value:String= input1   
    return toTuple(column, value) 
} 

val UdfCreateTuple = udf(createTuple _) 

[newColumnName,rowValue]とのタプルを含む新しい列を生成する(2)DataFrame

dfNew= df.select($"*", UdfCreateTuple($"col1",$"col2").alias("tmpCol") 

に関数を適用(3)異なる値を持つ配列を作成するnewColumnName

val dfDistinct = dfNew.select($"tmpCol.newColumnName").distinct 

(4)異なる値を持つ配列を作成

var a = dfDistinct.select($"newCol").rdd.map(r => r(0).asInstanceOf[String]) 

var arrDistinct = a.map(a => a).collect() 

(5)(6)は、元のデータフレームへのマッピングを適用し、キー値のマッピング

var seqMapping:Seq[(String,String)]=Seq() 
for (i <- arrDistinct){ 
    seqMapping :+= (i,i) 
} 

を作成し、参照Mapping a value into a specific column based on annother column

val exprsDistinct = seqMapping.map { case (key, target) => 
    when($"tmpCol.newColumnName" === key, $"tmpCol.rowValue").alias(target) } 

val dfFinal = dfNew.select($"*" +: exprsDistinct: _*) 

まあ、それは少し面倒ですが、私はそこにあると同時に、その新しい列に値を転送するどのように多くを知らなくても、新しい列のセットを導き出すことができます。

コメントをいただきありがとうございます。おそらくもっと速い方法がありますか?私は答えを共有するだろうと思ったので

ベスト、ケン

+0

こんにちはケン、私はあなたの質問に答えました。 – LucieCBurgess

1

は、私はあなたが:-)を尋ねた後、それは10ヶ月だ場合でも、私はあなたの質問に出くわしたと私が思った(私自身のデータフレームとまったく同じ問題を抱えていました答えは他人に役立つかもしれません。

  1. はCOL2
  2. //新しい列を追加し、「値と連結COL1の内容を含む新しい列を追加します。次のように
    val df3 = df2.withColumn("newCol", concat($"col1", $"col2")) //Step 1 
          .withColumn("value",when($"col3".isNotNull, $"col3").otherwise($"col4")) //Step 2 
          .groupBy($"col1",$"col2",$"col3",$"col4",$"newCol") //Step 3 
          .pivot("newCol") // Step 4 
          .agg(max($"value")) // Step 5 
          .orderBy($"newCol") // Step 6 
          .drop($"newCol") // Step 7 
    
         df3.show() 
    

    手順

    が仕事:簡単な方法がありますcol3またはcol4のnull以外の内容が含まれています
  3. GroupBy必要な列
  4. 今度は列見出しになる値が含まれています
  5. maxの値で集計します。groupByがグループごとに単一値の場合は値自体になります。値が文字列ではなく数値型であることを起こる場合は、代わり.agg(first($"value")) - 最大の機能だけでは、もはやそれを必要としないようにDFが順番
  6. ドロップこのコラムを昇順であるニューコールによって数値型
  7. ために適用することができますあなたはヌルなし

クレジット値の列をしたい場合、または原因@ user8371915私が最初の場所で自分のピボット質問に答える助けた人に、このステップをスキップします。次のように

結果は次のとおりです。

+----+----+----+----+----+----+----+ 
|col1|col2|col3|col4| AX| BZ| CY| 
+----+----+----+----+----+----+----+ 
| A| X| 6|null| 6|null|null| 
| B| Z|null| 5|null| 5|null| 
| C| Y| 4| 4|null|null| 4| 
+----+----+----+----+----+----+----+ 

あなたは正しい結果を得るために、列ヘッダー文字列の連結で遊んでする必要がある場合があります。

+1

@ user8371915、nice edit! :-) – LucieCBurgess

関連する問題