Apache spark 为什么在ApacheSparkSQL中列变为可空?

Apache spark 为什么在ApacheSparkSQL中列变为可空?,apache-spark,apache-spark-sql,apache-spark-dataset,Apache Spark,Apache Spark Sql,Apache Spark Dataset,为什么在执行某些函数后使用nullable=true,即使数据帧中没有NaN值 val myDf=Seq((2,“A”),(2,“B”),(1,“C”)) .toDF(“foo”、“bar”) .withColumn(“foo”),“foo.cast(“Int”)) myDf.withColumn(“foo_2”,当($“foo”==2,1)时。否则(0))。选择(“foo”,“foo_2”)。显示 现在调用df.printSchema时,两列的null将为false valfoo:(Int=

为什么在执行某些函数后使用
nullable=true
,即使
数据帧中没有NaN值

val myDf=Seq((2,“A”),(2,“B”),(1,“C”))
.toDF(“foo”、“bar”)
.withColumn(“foo”),“foo.cast(“Int”))
myDf.withColumn(“foo_2”,当($“foo”==2,1)时。否则(0))。选择(“foo”,“foo_2”)。显示
现在调用
df.printSchema
时,两列的
null
将为
false

valfoo:(Int=>String)=(t:Int)=>{
fooMap.get(t)匹配{
案例部分(tt)=>tt
案例无=>“未找到”
}
}
val fooMap=Map(
1->“小”,
2->“大”
)
val fooUDF=udf(foo)
myDf
.withColumn(“foo”,fooUDF(col(“foo”))
。使用列(“foo_2”,当($“foo”==2,1)。否则(0)。选择(“foo”,“foo_2”)
.选择(“foo”、“foo_2”)
.printSchema

但是现在,
nullable
对于至少一个以前为
false
的列是
true
。如何解释这一点?

当从静态类型结构(不依赖于
模式
参数)创建
数据集
时,Spark使用一组相对简单的规则来确定
可空的
属性

  • 如果给定类型的对象可以是
    null
    ,则其
    DataFrame
    表示形式为
    null
  • 如果对象是
    选项[\u]
    ,则其
    数据帧
    表示为
    可空
    ,且
    被视为SQL
  • 在任何其他情况下,它将被标记为不可为空
由于Scala
String
java.lang.String
,可以是
null
,所以生成的列可以是
null
。出于同样的原因,
bar
列在初始数据集中为
null

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[(整数,字符串)]((2,“A”),(2,“B”),(1,“C”))
foo
将是
null
Integer
java.lang.Integer
,装箱整数可以是
null
):

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

另请参见:修改ScalaUDF以处理可空性。

您也可以非常快速地更改dataframe的架构。像这样的东西就行了-

def setNullableStateForAllColumns( df: DataFrame, columnMap: Map[String, Boolean]) : DataFrame = {
    import org.apache.spark.sql.types.{StructField, StructType}
    // get schema
    val schema = df.schema
    val newSchema = StructType(schema.map {
    case StructField( c, d, n, m) =>
      StructField( c, d, columnMap.getOrElse(c, default = n), m)
    })
    // apply new schema
    df.sqlContext.createDataFrame( df.rdd, newSchema )
}