4

いくつかのカテゴリ文字列列を含むデータセットがあり、それらを double 型で表現したいと考えています。この変換に StringIndexer を使用しましたが、機能しますが、NULL 値を持つ別のデータセットで試してみると、java.lang.NullPointerExceptionエラーが発生して機能しませんでした。

理解を深めるために、私のコードは次のとおりです。

for(col <- cols){
    out_name = col ++ "_"
    var indexer = new StringIndexer().setInputCol(col).setOutputCol(out_name)
    var indexed = indexer.fit(df).transform(df)
    df = (indexed.withColumn(col, indexed(out_name))).drop(out_name)
}

では、StringIndexer を使用してこの NULL データの問題を解決するにはどうすればよいでしょうか?

または、NULL 値を持つ文字列型のカテゴリ データを double に変換するためのより良い解決策はありますか?

4

1 に答える 1

7

火花 >= 2.2

Spark 2.2NULLの値は standard で処理できるため:handleInvalid Param

import org.apache.spark.ml.feature.StringIndexer

val df = Seq((0, "foo"), (1, "bar"), (2, null)).toDF("id", "label")
val indexer = new StringIndexer().setInputCol("label")

デフォルト ( error) では、例外がスローされます。

indexer.fit(df).transform(df).show
org.apache.spark.SparkException: Failed to execute user defined function($anonfun$9: (string) => double)
  at org.apache.spark.sql.catalyst.expressions.ScalaUDF.eval(ScalaUDF.scala:1066)
...
Caused by: org.apache.spark.SparkException: StringIndexer encountered NULL value. To handle or skip NULLS, try setting StringIndexer.handleInvalid.
  at org.apache.spark.ml.feature.StringIndexerModel$$anonfun$9.apply(StringIndexer.scala:251)
...

しかし、skip

indexer.setHandleInvalid("skip").fit(df).transform(df).show
+---+-----+---------------------------+
| id|label|strIdx_46a78166054c__output|
+---+-----+---------------------------+
|  0|    a|                        0.0|
|  1|    b|                        1.0|
+---+-----+---------------------------+

またはkeep

indexer.setHandleInvalid("keep").fit(df).transform(df).show
+---+-----+---------------------------+
| id|label|strIdx_46a78166054c__output|
+---+-----+---------------------------+
|  0|    a|                        0.0|
|  1|    b|                        1.0|
|  3| null|                        2.0|
+---+-----+---------------------------+

スパーク < 2.2

現在 (Spark 1.6.1) では、この問題は解決されていませんが、開いている JIRA ( SPARK-11569 ) があります。残念ながら、許容できる動作を見つけるのは簡単ではありません。SQL NULL は欠落/不明な値を表すため、インデックス作成は意味がありません。

おそらく、あなたができる最善のことは、NAアクションを使用して、次のいずれかをドロップすることです。

df.na.drop("column_to_be_indexed" :: Nil)

または記入してください:

df2.na.fill("__HEREBE_DRAGONS__", "column_to_be_indexed" :: Nil)

インデクサーを使用する前に。

于 2016-03-20T12:08:26.017 に答える