scala - 对 Spark 数据框的列求和并创建另一个数据框
问题描述
我有一个如下所示的数据框 -
我正在尝试从中创建另一个数据框,它有 2 列 - 列名和每列中的值总和,如下所示 -
到目前为止,我已经尝试过这个(在 Spark 2.2.0 中)但抛出了一个堆栈跟踪 -
val get_count: (String => Long) = (c: String) => {
df.groupBy("id")
.agg(sum(c) as "s")
.select("s")
.collect()(0)
.getLong(0)
}
val sqlfunc = udf(get_count)
summary = summary.withColumn("sum_of_column", sqlfunc(col("c")))
是否有其他替代方法可以完成此任务?
解决方案
我认为最有效的方法是进行聚合,然后构建一个新的数据框。这样你就避免了昂贵的explode
.
首先,让我们创建数据框。顺便说一句,当您提出问题时,提供代码来做这件事总是很好的。这样我们可以在几秒钟内重现您的问题。
val df = Seq((1, 1, 0, 0, 1), (1, 1, 5, 0, 0),
(0, 1, 0, 6, 0), (0, 1, 0, 4, 3))
.toDF("output_label", "ID", "C1", "C2", "C3")
然后我们构建我们感兴趣的列列表、聚合,并计算结果。
val cols = (1 to 3).map(i => s"C$i")
val aggs = cols.map(name => sum(col(name)).as(name))
val agg_df = df.agg(aggs.head, aggs.tail :_*) // See the note below
agg_df.show
+---+---+---+
| C1| C2| C3|
+---+---+---+
| 5| 10| 4|
+---+---+---+
我们几乎拥有了我们需要的东西,我们只需要收集数据并构建一个新的数据框:
val agg_row = agg_df.first
cols.map(name => name -> agg_row.getAs[Long](name))
.toDF("column", "sum")
.show
+------+---+
|column|sum|
+------+---+
| C1| 5|
| C2| 10|
| C3| 4|
+------+---+
编辑:
注意:df.agg(aggs.head, aggs.tail :_*)
可能看起来很奇怪。这个想法只是简单地计算在 中计算的所有聚合aggs
。人们会期待更简单的东西,例如df.agg(aggs : _*)
. 然而,该agg
方法的签名如下:
def agg(expr: org.apache.spark.sql.Column,exprs: org.apache.spark.sql.Column*)
也许是为了确保至少使用一列,这就是为什么你需要拆分and aggs
。aggs.head
aggs.tail
推荐阅读
- ios - 当给 stackView 添加标签时,它会添加 4 个标签,而不是 5 个标签。Swift
- json - 如何制作一个不会缩小的变量?
- reactjs - 升级到最新版本后反应本机应用程序的奇怪行为
- java - "
预期,使用 FTS 标记器时出现“结束”错误 - python - 使用 json_normalize 在列表中展平双重嵌套字典
- postgresql - 在 yaml 中为 ruby 编码 Azure postgres dbstring
- python - 我怎样才能在一定时间内抓住所有被禁止的成员?
- python - 使用熊猫计算日期之间的日期
- php - Laravel - Eloquent 模型不触发事件
- reactjs - 有没有办法使打字稿中的对象仅在使用道具时才有效?