类型化列的总和计算结果为 NULL



我正在尝试通过获取数据帧中一组列的行值的总和来创建总和列。所以我按照以下方法去做。

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
+---+---+---+
|  A|  B|sum|
+---+---+---+
|  1|  5|  6|
|  2|  4|  6|
|  3|  7| 10|
|  4|  6| 10|
+---+---+---+

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

val cols2 = temp_data.columns.map(x=>typedLit(x)).toList

当我看colscols2时,它们看起来一模一样。

cols: List[org.apache.spark.sql.Column] = List(A, B)
cols2: List[org.apache.spark.sql.Column] = List(A, B)

但是,当我使用 cols2 创建我的 sum 列时,它并没有按照我期望的方式工作。

temp_data.withColumn("sum", cols2.reduce(_ + _)).show
+---+---+----+
|  A|  B| sum|
+---+---+----+
|  1|  5|null|
|  2|  4|null|
|  3|  7|null|
|  4|  6|null|
+---+---+----+

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

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相比,它并没有提供任何实际优势。

您正在尝试使用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|
+---+---+---+

谢谢

最新更新