2017-09-12 1 views
1

私はApache Spark 2.1.1を使用しています。算術比較のためにInt値を含む文字列にはキャスティングが必要ですか?

私は次のようにデータセットを持っています。

final case class TestModel(id: String, 
         code: String, 
         measure: String, 
         value: String) 

私はcsvファイルから適切にロードしています。異なるmeasure値の場合、valueデータ型が異なる可能性があります。例えば。 measureが 'Age'の場合、valueは文字列の年齢になります。ここでいくつかの処理を行うために、valueをIntegerTypeにキャストして、別のデータセットで指定された年齢の範囲との比較を行っています。 これを行うには、以下の正しい方法がありますか?

val testData = spark.read.schema(testSchema).option("header", "false").csv(dataPath).as[TestModel] 
val ageBasedTestData = testData.filter($"measure" === "Age") 


var ageBasedData = ageBasedTestData.join(anotherDS, ageBasedTestData("code") === anotherDS("code") && 
           anotherDS("ages").getItem(0) <= ageBasedTestData("value").cast(IntegerType) && 
           anotherDS("ages").getItem(1) > ageBasedTestData("value").cast(IntegerType)) 
           .select(some column names) 

これを行うの年齢範囲との比較の前にInterger型にvalue列の上記鋳造正しい方法はありますか?基本的には、文字列を比較目的のためにIntに変換していますが、データ型は気にしません。私は、キャストとキャストの両方でコードを実行して、両方私は同じ結果を与える。だから私はキャストなしで何が起こっているのかわからない。自動的に文字列をIntにキャストして比較しますか?重要であれば、anotherDSデータセットからの "age"配列のデータ型はIntegerです。

+0

udf関数を使うことをお勧めします。ちょうどそれらに参加し、後でudf関数を使用してフィルタを適用してください –

+1

@RameshMaharjan私はudf関数は最適化できないので、落胆していると思います。また、私はこの単純な文脈のためにudfが必要だとは思わない。 – user238607

答えて

2

私はキャストなしで何が起こっているのか分かりません。だから、

scala> spark.sql("SELECT 1 < '42'").explain(true) 
== Parsed Logical Plan == 
'Project [unresolvedalias((1 < 42), None)] 
+- OneRowRelation$ 

== Analyzed Logical Plan == 
(1 < CAST(42 AS INT)): boolean 
Project [(1 < cast(42 as int)) AS (1 < CAST(42 AS INT))#142] 
+- OneRowRelation$ 

== Optimized Logical Plan == 
Project [true AS (1 < CAST(42 AS INT))#142] 
+- OneRowRelation$ 

== Physical Plan == 
*Project [true AS (1 < CAST(42 AS INT))#142] 
+- Scan OneRowRelation[] 

scala> spark.sql("SELECT '42' < 1").explain(true) 
== Parsed Logical Plan == 
'Project [unresolvedalias((42 < 1), None)] 
+- OneRowRelation$ 

== Analyzed Logical Plan == 
(CAST(42 AS INT) < 1): boolean 
Project [(cast(42 as int) < 1) AS (CAST(42 AS INT) < 1)#147] 
+- OneRowRelation$ 

== Optimized Logical Plan == 
Project [false AS (CAST(42 AS INT) < 1)#147] 
+- OneRowRelation$ 

== Physical Plan == 
*Project [false AS (CAST(42 AS INT) < 1)#147] 
+- Scan OneRowRelation[] 

1つの引数が数値であれば、二番目がキャストされます。

は、実行計画を見てみましょう。

それはまだ強くようなミスを避けるために必要な種類のにデータをキャストすることをお勧めします。キャストの規則はトリッキーなと少し矛盾していることを、あなたが考える場合は特に

spark.sql("SELECT '42' < '9'") 

を:

scala> spark.sql("SELECT to_date('2015-01-01') < '2012-01-01'").explain 
== Physical Plan == 
*Project [false AS (CAST(to_date('2015-01-01') AS STRING) < 2012-01-01)#4] 
+- Scan OneRowRelation[] 
+0

分析をお寄せいただきありがとうございます。私のケースでこれを行い、結果を分析しましょう。それから私は答えを受け入れる。 – user238607

+0

キャストの有無にかかわらずqueryExecutionプランを分析しました。キャストの場合、キャストなしの場合は2倍のデータ型にキャストされていたのに対し、キャストはIntデータ型に正しくキャストされていました。 – user238607

関連する問題