2016-04-07 8 views
3

に基づいて、列の値を設定:SPARK:私は以下のフォーマットのデータフレームを有する複数の行条件

+----+---+-----+------+-----+------+ 
|AGEF|SEX|F0_34|F35_44|M0_34|M35_44| 
+----+---+-----+------+-----+------+ 
| 30| 0| 0|  0| 0|  0| 
| 94| 1| 0|  0| 0|  0| 
| 94| 0| 0|  0| 0|  0| 
| 94| 0| 0|  0| 0|  0| 
| 94| 1| 0|  0| 0|  0| 
| 44| 0| 0|  0| 0|  0| 
| 66| 0| 0|  0| 0|  0| 
| 66| 0| 0|  0| 0|  0| 
| 74| 0| 0|  0| 0|  0| 
| 74| 0| 0|  0| 0|  0| 
| 29| 0| 0|  0| 0|  0| 

今は列名を対応する1を割り当てる必要が列AGEFの値および性別に基づきます。 F0_34は、他のケースと同様に年齢0〜34歳の女性のように、各列名は自明です。

の予想される出力は、事前に

+----+---+-----+------+-----+------+ 
|AGEF|SEX|F0_34|F35_44|M0_34|M35_44| 
+----+---+-----+------+-----+------+ 
| 30| 0| 1|  0| 0|  0| 
| 94| 1| 0|  0| 0|  0| 
| 94| 0| 0|  0| 0|  0| 
| 94| 0| 0|  0| 0|  0| 
| 94| 1| 0|  0| 0|  0| 
| 44| 0| 0|  1| 0|  0| 
| 66| 0| 0|  0| 0|  0| 
| 66| 0| 0|  0| 0|  0| 
| 74| 0| 0|  0| 0|  0| 
| 74| 0| 0|  0| 0|  0| 
| 29| 0| 1|  0| 0|  0| 

感謝です! (:actual_age、actual_sex、target_sex、target_min_age、target_max_ageなど)と、このような1つのまたは0の何かを返す:あなたが持っていた場合、

val ageRanger = udf[Int,Int,Int,Int,Int,Int]((age: Int, sex: Int, targetSex: Int, targetMinAge: Int, targetMaxAge: Int) => { 
    if (age >= targetMinAge && age <= targetMaxAge && sex == targetSex) 1 else 0 
}) 

答えて

4

通常、最も効率的なアプローチは、SQL式に対して直接操作することです。例:

def categorize(ageRanges: Seq[(Int, Int)], sexValues: Seq[(Int, String)]) = for { 
    (ageL, ageH) <- ageRanges 
    (sexV, sexL) <- sexValues 
} yield ($"SEX" === sexL && $"AGEF".between(ageL, ageH)).alias(
    s"$sexL-$ageL-$ageH" 
) 

df.select(
    $"*" +: categorize(Seq((0, 34), (35, 44)), Seq((0, "F"), (1, "M"))): _* 
) 
3

最も簡単な方法は、5つのパラメータを取るUDFを作ることですこのDataFrame:あなたはColumnsとしてUDFに値を渡す必要があり、私はハードコードされた値のための私のInt値をラップするlit(...)を使用

val df = Seq((30,0),(94,1),(94,0),(44,0)).toDF("AGEF", "SEX") 
// +----+---+ 
// |AGEF|SEX| 
// +----+---+ 
// | 30| 0| 
// | 94| 1| 
// | 94| 0| 
// | 44| 0| 
// +----+---+ 

df.withColumn("F0_34", ageRanger($"AGEF", $"SEX", lit(0), lit(0), lit(34))) 
    .withColumn("F35_44", ageRanger($"AGEF", $"SEX", lit(0), lit(35), lit(44))) 
    .show 
// +----+---+-----+------+ 
// |AGEF|SEX|F0_34|F35_44| 
// +----+---+-----+------+ 
// | 30| 0| 1|  0| 
// | 94| 1| 0|  0| 
// | 94| 0| 0|  0| 
// | 44| 0| 0|  1| 
// +----+---+-----+------+ 

注意。それを行うためには、より滑らかな方法があるかもしれませんが、それはこのようにうまく機能します。

関連する問題