2017-04-05 9 views
3

データにnull値を持つRDD[(Seq[String], Seq[String])]があります。私はそれがスロー示して打つようしかし、すぐに、String型のnullable scala.matcherrorの一部(null)

val rdd = sc.parallelize(Seq((Seq("111","aaa"),Seq("xx",null)))) 
val df = rdd.toDF("col1","col2") 
val keys = Array("col1","col2") 
val values = df.flatMap { 
    case Row(t1: Seq[String], t2: Seq[String]) => Some((t1 zip t2).toMap) 
    case Row(_, null) => None 
} 
val transposed = values.map(someFunc(keys)) 

val schema = StructType(keys.map(name => StructField(name, DataTypes.StringType, nullable = true))) 

val transposedDf = sc.createDataFrame(transposed, schema) 

transposed.show() 

それは私がtransposedDFを作成する時点まで正常に動作: RDDは、データフレームに変換するには、サンプルコードは以下のこの

+----------+----------+ 
|  col1|  col2| 
+----------+----------+ 
|[111, aaa]|[xx, null]| 
+----------+----------+ 

のように見えます次のエラーが発生しました:

scala.MatchError: null 
     at org.apache.spark.sql.catalyst.CatalystTypeConverters$StringConverter$.toCatalystImpl(CatalystTypeConverters.scala:295) 
     at org.apache.spark.sql.catalyst.CatalystTypeConverters$StringConverter$.toCatalystImpl(CatalystTypeConverters.scala:294) 
     at org.apache.spark.sql.catalyst.CatalystTypeConverters$CatalystTypeConverter.toCatalyst(CatalystTypeConverters.scala:97) 
     at org.apache.spark.sql.catalyst.CatalystTypeConverters$StructConverter.toCatalystImpl(CatalystTypeConverters.scala:260) 
     at org.apache.spark.sql.catalyst.CatalystTypeConverters$StructConverter.toCatalystImpl(CatalystTypeConverters.scala:250) 
     at org.apache.spark.sql.catalyst.CatalystTypeConverters$CatalystTypeConverter.toCatalyst(CatalystTypeConverters.scala:102) 
     at org.apache.spark.sql.catalyst.CatalystTypeConverters$$anonfun$createToCatalystConverter$2.apply(CatalystTypeConverters.scala:401) 
     at org.apache.spark.sql.SQLContext$$anonfun$6.apply(SQLContext.scala:492) 
     at org.apache.spark.sql.SQLContext$$anonfun$6.apply(SQLContext.scala:492) 

この場合、コードが正常に動作します。私はnull値があるときになぜ失敗するのか理解できません。なぜなら、nullableをtrueにしてStringTypeのスキーマを指定しているからです。何か間違っているのですか?

case Row(t1: Seq[String], t2: Seq[String]) => Some((t1 zip t2).toMap) 

T1の値に制限はありません:私は、この行を、それがソースに表示されるように、パターンマッチが直線的に行われる2.10

答えて

1

スパーク1.6.1とスカラ座を使用して、そうしていますt2は決してヌル値と一致しません。

効果的に、ヌルチェックを入れると効果があります。

+2

IIUCでは、型パターンはnullと決して一致しません.b/c instanceofは常にfalseです。 –

+0

@ som-snytt、あなたは正しいです。 – pedrofurla

0

アサーション操作を実行する前に、null値を空白または特殊文字列にエンコードする必要があると思います。また、Sparkは遅れて実行されることに注意してください。ですから、 "val values = df.flatMap"のようなものからは、すべてがshow()が実行されたときにのみ実行されます。

1

nullが最初のパターンと一致するかどうかは問題です。やはりt2: Seq[String]は、理論的にはnullとなります。 nullパターンを最初に表示するだけですぐに解決できるのは当然ですが、Scala言語の機能を使用してnullを完全に取り除き、ランタイムの驚きを避けることが不可欠です。

ですから、このような何か行うことができます:

def foo(s: Seq[String]) = if (s.contains(null)) None else Some(s) 
//or you could do fancy things with filter/filterNot 

df.map { 
    case (first, second) => (foo(first), foo(second)) 
} 

をこれは、あなたがしたいように見えるタプルをSome/Noneを提供しますが、私はそれらのNoneのようにうまく平坦化については見るであろう。

関連する問題