typedLit列的总和计算为NULL

时间:2019-01-17 21:00:24

标签: scala apache-spark apache-spark-sql

我试图通过获取数据帧中一组列的行值之和来创建一个sum列。因此,我按照以下方法进行操作。

AnnotationOne
val temp_data = spark.createDataFrame(Seq(
  (1, 5),
  (2, 4),
  (3, 7),
  (4, 6)
)).toDF("A", "B")

val cols  = List(col("A"), col("B"))
temp_data.withColumn("sum", cols.reduce(_ + _)).show

因此,此方法可以正常工作并产生预期的输出。但是,我想创建cols变量而不显式指定列名。因此,我使用typedLit如下。

+---+---+---+
|  A|  B|sum|
+---+---+---+
|  1|  5|  6|
|  2|  4|  6|
|  3|  7| 10|
|  4|  6| 10|
+---+---+---+

当我看着val cols2 = temp_data.columns.map(x=>typedLit(x)).toList cols时,它们看起来完全一样。

cols2

但是,当我使用cols: List[org.apache.spark.sql.Column] = List(A, B) cols2: List[org.apache.spark.sql.Column] = List(A, B) 创建求和列时,它无法按我期望的方式工作。

cols2
temp_data.withColumn("sum", cols2.reduce(_ + _)).show

有人知道我在做什么错吗?为什么第二种方法不能像第一种方法那样工作?

2 个答案:

答案 0 :(得分:2)

littypedLit不能代替Column。您的代码会创建一个字符串文字列表-"A""B"

temp_data.select(cols2: _*).show
+---+---+
|  A|  B|
+---+---+
|  A|  B|
|  A|  B|
|  A|  B|
|  A|  B|
+---+---+

并要求它们的总和-因此结果是不确定的。

您可以在此处使用TypedColumn

import org.apache.spark.sql.TypedColumn

val typedSum: TypedColumn[Any, Int] = cols.map(_.as[Int]).reduce{ 
  (x, y) => (x + y).as[Int]
}

temp_data.withColumn("sum", typedSum).show

但是与此处的标准Column相比,它没有任何实际的优势。

答案 1 :(得分:2)

您正在尝试使用不正确的typedLit,就像提到的其他答案一样,您不必在TypedColumn中使用函数。您只需在数据框的列上使用映射转换即可将其转换为List(Col)

将您的cols2语句更改为以下内容并尝试。

val cols  = temp_data.columns.map(f=> col(f))
temp_data.withColumn("sum", cols.reduce(_ + _)).show

您将获得以下输出。

+---+---+---+
|  A|  B|sum|
+---+---+---+
|  1|  5|  6|
|  2|  4|  6|
|  3|  7| 10|
|  4|  6| 10|
+---+---+---+

谢谢