2016-11-15 27 views
6

爲什麼在執行某些函數後nullable = true?在df中仍然沒有nan值。火花爲什麼列更改爲可空

val myDf = Seq((2,"A"),(2,"B"),(1,"C")) 
     .toDF("foo","bar") 
     .withColumn("foo", 'foo.cast("Int")) 

myDf.withColumn("foo_2", when($"foo" === 2 , 1).otherwise(0)).select("foo", "foo_2").show 

df.printSchema被稱爲現在可空將是兩列假的。

val foo: (Int => String) = (t: Int) => { 
    fooMap.get(t) match { 
     case Some(tt) => tt 
     case None => "notFound" 
    } 
    } 

val fooMap = Map(
    1 -> "small", 
    2 -> "big" 
) 
val fooUDF = udf(foo) 

myDf 
    .withColumn("foo", fooUDF(col("foo"))) 
    .withColumn("foo_2", when($"foo" === 2 , 1).otherwise(0)).select("foo", "foo_2") 
    .select("foo", "foo_2") 
    .printSchema 

但是現在,對於至少一個之前爲假的列,可爲空值爲真。這怎麼解釋?

回答

6

從靜態類型結構創建Dataset時(不依賴於schema參數)Spark使用相對簡單的一組規則來確定nullable屬性。

  • 如果給定類型的對象可以是null然後其DataFrame表示是nullable
  • 如果對象是Option[_],那麼它的DataFrame表示是nullableNone被認爲是SQL NULL
  • 在任何其他情況下,它將被標記爲不是nullable

由於Scala的Stringjava.lang.String,其可以是null,產生可以列是nullable。出於同樣的原因bar柱處於初始數據集nullable

val data1 = Seq[(Int, String)]((2, "A"), (2, "B"), (1, "C")) 
val df1 = data1.toDF("foo", "bar") 
df1.schema("bar").nullable 
Boolean = true 

foo但不是(scala.Int不能null)。

df1.schema("foo").nullable 
Boolean = false 

如果我們改變數據定義:

val data2 = Seq[(Integer, String)]((2, "A"), (2, "B"), (1, "C")) 

foonullableIntegerjava.lang.Integer和盒裝整數可以是null):

data2.toDF("foo", "bar").schema("foo").nullable 
Boolean = true 

另請參閱:SPARK-20668修改ScalaUDF以處理空函數