我试图通过获取数据帧中一组列的行值之和来创建一个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
有人知道我在做什么错吗?为什么第二种方法不能像第一种方法那样工作?
答案 0 :(得分:2)
lit
或typedLit
不能代替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|
+---+---+---+
谢谢