2016-11-15 26 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以处理空函数