我是scala / spark的新手。我正在使用spark上的scala / java应用程序,尝试从hive表中读取一些数据,然后总结每行的所有列值。例如,考虑以下DF:
+--------+-+-+-+-+-+-+
| address|a|b|c|d|e|f|
+--------+-+-+-+-+-+-+
|Newyork |1|0|1|0|1|1|
| LA |0|1|1|1|0|1|
|Chicago |1|1|0|0|1|1|
+--------+-+-+-+-+-+-+
我想总结所有行中的所有1并得到total.i.e。上面的数据帧的所有列的总和应该是12(因为在所有行中有12个1的组合)
我试过这样做:
var count = 0
DF.foreach( x => {
count = count + Integer.parseInt(x.getAs[String]("a")) + Integer.parseInt(x.getAs[String]("b")) + Integer.parseInt(x.getAs[String]("c")) + Integer.parseInt(x.getAs[String]("d")) + Integer.parseInt(x.getAs[String]("e")) + Integer.parseInt(x.getAs[String]("f"))
})
运行上述代码时,count
值仍为zero
。我认为这与在群集上运行应用程序有关。因此,声明一个变量并添加它对我来说不起作用,因为我必须在一个集群上运行我的应用程序。我也尝试在一个单独的java类中声明静态变量并添加它 - 这给了我相同的结果。
据我所知,应该有一种简单的方法可以使用spark / scala库中提供的内联函数来实现这一点。
实现这一目标的有效方法是什么?任何帮助将不胜感激。
谢谢。
P.S:我正在使用Spark 1.6。
答案 0 :(得分:1)
您可以先对列值求和,然后返回sum
s的单行数据帧,然后将此行转换为Seq并将值相加:
val sum_cols = df.columns.tail.map(x => sum(col(x)))
df.agg(sum_cols.head, sum_cols.tail: _*).first.toSeq.asInstanceOf[Seq[Long]].sum
// res9: Long = 12
df.agg(sum_cols.head, sum_cols.tail: _*).show
+------+------+------+------+------+------+
|sum(a)|sum(b)|sum(c)|sum(d)|sum(e)|sum(f)|
+------+------+------+------+------+------+
| 2| 2| 2| 1| 2| 3|
+------+------+------+------+------+------+
答案 1 :(得分:0)
这是另一种方法:
首先让我们准备一个聚合函数:
scala> val f = df.drop("address").columns.map(col).reduce((c1, c2) => c1 + c2)
f: org.apache.spark.sql.Column = (((((a + b) + c) + d) + e) + f)
将sum作为DataFrame获取:
scala> df.agg(sum(f).alias("total")).show
+-----+
|total|
+-----+
| 12|
+-----+
将总和作为Long
数字:
scala> df.agg(sum(f)).first.getLong(0)
res39: Long = 12