带有空值的 Seq[(Int,Int)] 隐式转换为 DataFrame

Posted

技术标签:

【中文标题】带有空值的 Seq[(Int,Int)] 隐式转换为 DataFrame【英文标题】:Seq[(Int,Int)] with nulls implicitly converted to DataFrame 【发布时间】:2018-10-24 01:40:22 【问题描述】:

我有一个简单的测试用例,将Seq[(Int,Int)] 转换为 DataFrame:

test("SparkTest 0280") 
  val conf = new SparkConf().set("spark.sql.codegen.wholeStage", "false").set("spark.sql.cbo.enabled", "true")
  val spark = SparkSession.builder().config(conf).master("local").appName("SparkTest").enableHiveSupport().getOrCreate()

  import spark.implicits._

  Seq[(Int,Int)]((null, 1), (2, null), (null, 3)).toDF("a", "b").createOrReplaceTempView("t")
  spark.sql("select a,b,nvl(a,b) from t").show(truncate = false)

编译有问题:

Error:(565, 21) an expression of type Null is ineligible for implicit conversion
    Seq[(Int,Int)]((null, 1), (2, null), (null, 3)).toDF("a", "b").createOrReplaceTempView("t")

这里有什么问题?

【问题讨论】:

【参考方案1】:

您不能像这样直接使用null,因为创建的列的类型为Any(不允许用于数据框)。这可以通过创建 RDD 来确认:

val rdd: RDD[(Any, Any)] = spark.sparkContext.parallelize(Seq((null, 1), (2, null), (null, 3)))

这是由于 Int 在 Scala 中不可为空,来自 Scala tour:

有九种预定义的值类型,它们不可为空:DoubleFloatLongIntShortByteCharUnit 和 @ 987654334@.

可以直接使用null 创建具有其他数据类型(如字符串)的列,否则一个简单的解决方案是使用NoneSome

Seq((None, Some(1)), (Some(2), None), (None, Some(3))).toDF("a", "b"))

【讨论】:

【参考方案2】:

如果你想使用nulls,你应该用java.lang.Integers替换Ints

Seq[(Integer, Integer)]((null, 1), (2, null), (null, 3)).toDF("a", "b")
// org.apache.spark.sql.DataFrame = [a: int, b: int]

可以为空。

【讨论】:

是的,谢谢,scala 值类型在处理空值时有点不灵活

以上是关于带有空值的 Seq[(Int,Int)] 隐式转换为 DataFrame的主要内容,如果未能解决你的问题,请参考以下文章

请问double型可以强制转换成int型吗?

如何使用带有可空值的吸气剂?

不能隐式转换类型“int?”到'int'。

数据框空值在 UDF 之后转换为 0。为啥?

java 强制类型转换的规则是啥?

为啥空字符串上的 .ToString() 会导致空错误,而 .ToString() 在具有空值的可空 int 上工作正常?