Spark数据集是否使用空值减少?

时间:2017-03-31 13:55:16

标签: scala apache-spark

我使用以下代码创建数据框:

...

然后我将我的udf应用于它:

  val data = List(
    List(444.1235D),
    List(67.5335D),
    List(69.5335D),
    List(677.5335D),
    List(47.5335D),
    List(null)
  )

  val rdd = sparkContext.parallelize(data).map(Row.fromSeq(_))
  val schema = StructType(Array(
    StructField("value", DataTypes.DoubleType, true)
  ))

  val df = sqlContext.createDataFrame(rdd, schema)

然后我尝试在此数据集上使用reduce:

val multip: Dataset[Double] = df.select(doubleUdf(df("value"))).as[Double]

在这里我得到了0.0。 我还尝试过滤掉空值

val multipl = multip.reduce(_ * _)

具有相同的结果。 如果我从数据中删除null值,一切正常。如何使用空值减少工作?

我的udf定义如下:

val multipl = multip.filter(_ != null).reduce(_ * _)

2 个答案:

答案 0 :(得分:5)

我会强烈假设您的doubleUdf函数将值转换为双精度,而不是使用Option包装器来表示空值,而是将空值转换为0.0。所以,如果你想保持逻辑删除空值,那么过滤掉其他任何东西:

df.na.drop.select(doubleUdf(df("value"))).as[Double]

答案 1 :(得分:2)

首先,我会问你为什么甚至根本不和null打交道。我会评估我阅读数据的方式,以确保不会发生。

然后我会注意到你可以在内存null之前删除List,然后才能达到RDD级别,例如:

data.flatMap(Option(_)).flatten

但是如果你必须在RDD级别处理null,你有选择(没有双关语):

sparkContext.parallelize(data).filter(!_.contains(null))

sparkContext.parallelize(data).map(_.flatMap(Option(_))).filter(_.nonEmpty)

我更喜欢后者。我不喜欢在Scala代码中查看null

我会远离基于UDF的解决方案,因为Spark无法优化UDF,而且丢失Spark的优化功能是一种耻辱,而不是像null那样蹩脚。