Spark DataFrame
に以下のSQLロジックを実装する必要があります
SELECT KEY,
CASE WHEN tc in ('a','b') THEN 'Y'
WHEN tc in ('a') AND amt > 0 THEN 'N'
ELSE NULL END REASON,
FROM dataset1;
私の入力DataFrame
は次のとおりです。
val dataset1 = Seq((66, "a", "4"), (67, "a", "0"), (70, "b", "4"), (71, "d", "4")).toDF("KEY", "tc", "amt")
dataset1.show()
+---+---+---+
|KEY| tc|amt|
+---+---+---+
| 66| a| 4|
| 67| a| 0|
| 70| b| 4|
| 71| d| 4|
+---+---+---+
ネストされたcase whenステートメントを次のように実装しました。
dataset1.withColumn("REASON", when(col("tc").isin("a", "b"), "Y")
.otherwise(when(col("tc").equalTo("a") && col("amt").geq(0), "N")
.otherwise(null))).show()
+---+---+---+------+
|KEY| tc|amt|REASON|
+---+---+---+------+
| 66| a| 4| Y|
| 67| a| 0| Y|
| 70| b| 4| Y|
| 71| d| 4| null|
+---+---+---+------+
「otherwise」ステートメントを使用した上記のロジックの可読性は、ネストされたwhenステートメントがさらに進んだ場合、少し乱雑になります。
Spark DataFrames
?のステートメントの場合、ネストされたケースを実装するより良い方法はありますか?
ここにはネストがないため、otherwise
は必要ありません。必要なのは、チェーンされたwhen
:
import spark.implicits._
when($"tc" isin ("a", "b"), "Y")
.when($"tc" === "a" && $"amt" >= 0, "N")
ELSE NULL
は暗黙的であるため、完全に省略することができます。
使用するパターンは、データ構造上のfolding
により適しています。
val cases = Seq(
($"tc" isin ("a", "b"), "Y"),
($"tc" === "a" && $"amt" >= 0, "N")
)
ここで、when
-otherwise
は再帰パターンに自然に従い、null
は基本ケースを提供します。
cases.foldLeft(lit(null)) {
case (acc, (expr, value)) => when(expr, value).otherwise(acc)
}
この一連の条件では、「N」の結果に到達することは不可能であることに注意してください。 tc
が「a」に等しい場合、最初の句によってキャプチャされます。そうでない場合は、両方の述部を満たすことができず、デフォルトはNULL
になります。むしろ:
when($"tc" === "a" && $"amt" >= 0, "N")
.when($"tc" isin ("a", "b"), "Y")
より複雑なロジックの場合、読みやすくするためにUDFを使用することを好みます。
val selectCase = udf((tc: String, amt: String) =>
if (Seq("a", "b").contains(tc)) "Y"
else if (tc == "a" && amt.toInt <= 0) "N"
else null
)
dataset1.withColumn("REASON", selectCase(col("tc"), col("amt")))
.show
データセットでselectExprを使用するだけです
dataset1.selectExpr("*", "CASE WHEN tc in ('a') AND amt > 0 THEN 'N' WHEN tc in ('a','b') THEN 'Y' ELSE NULL END
REASON").show()
+---+---+---+------+
|KEY| tc|amt|REASON|
+---+---+---+------+
| 66| a| 4| N|
| 67| a| 0| Y|
| 70| b| 4| Y|
| 71| d| 4| null|
+---+---+---+------+
最初の条件はより一般的な条件であるため、2番目の条件は最初の条件の前に配置する必要があります。
Tc in( 'a')AND amt> 0 THEN 'N'の場合