带有空值的 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:
有九种预定义的值类型,它们不可为空:
Double
、Float
、Long
、Int
、Short
、Byte
、Char
、Unit
和 @ 987654334@.
可以直接使用null
创建具有其他数据类型(如字符串)的列,否则一个简单的解决方案是使用None
和Some
:
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的主要内容,如果未能解决你的问题,请参考以下文章
为啥空字符串上的 .ToString() 会导致空错误,而 .ToString() 在具有空值的可空 int 上工作正常?