我正在使用Spark 1.60
和Scala 2.10.5
我有一个这样的数据框,
+------------------+
|id | needed |
+------------------+
|1 | 2 |
|1 | 0 |
|1 | 3 |
|2 | 0 |
|2 | 0 |
|3 | 1 |
|3 | 2 |
+------------------+
从此df
我创建了一个rdd
,
val dfRDD = df.rdd
从我的rdd
开始,我想按id
分组,而needed
的计数为> 0
。
(((1,2),(2,0),(3,2))
所以,我尝试过这样,
val groupedDF = dfRDD.map(x =>(x(0), x(1) > 0)).count.redueByKey(_+_)
在这种情况下,我得到一个错误:
错误:值>不是任何成员
我需要rdd
级的。任何获得我想要的输出的帮助都会很棒。
答案 0 :(得分:2)
无需在rdd
级别进行计算。与数据框的聚合应该起作用:
df.groupBy("id").agg(sum(($"needed" > 0).cast("int")).as("positiveCount")).show
+---+-------------+
| id|positiveCount|
+---+-------------+
| 1| 2|
| 3| 2|
| 2| 0|
+---+-------------+
如果必须使用RDD,请使用row.getInt
或作为@Luis的答案row.getAs[Int]
获得具有显式类型的值,然后进行比较和reduceByKey
:>
df.rdd.map(r => (r.getInt(0), if (r.getInt(1) > 0) 1 else 0)).reduceByKey(_ + _).collect
// res18: Array[(Int, Int)] = Array((1,2), (2,0), (3,2))
答案 1 :(得分:2)
问题是,在您的map
中,您正在调用行的apply
方法,并且您可以在其{ {3}}中,该方法返回任何-正如您所看到的错误一样,在scaladoc中没有这样的方法 <
in Any
您可以使用getAs[T]
方法对其进行修复。
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.SparkSession
val spark =
SparkSession
.builder
.master("local[*]")
.getOrCreate()
import spark.implicits._
val df =
List(
(1, 2),
(1, 0),
(1, 3),
(2, 0),
(2, 0),
(3, 1),
(3, 2)
).toDF("id", "needed")
val rdd: RDD[(Int, Int)] = df.rdd.map(row => (row.getAs[Int](fieldName = "id"), row.getAs[Int](fieldName = "needed")))
从那里您可以继续进行汇总,逻辑上有一些错误。
首先,您不需要count
调用。
其次,如果您需要计算"needed"
大于1的次数,则您无法计算_ + _
,因为那是所需值的总和。
val grouped: RDD[(Int, Int)] = rdd.reduceByKey { (acc, v) => if (v > 0) acc + 1 else acc }
val result: Array[(Int, Int)] = grouped.collect()
// Array((1,3), (2,0), (3,2))
PS:您应该告诉您的教授升级到Spark 2和Scala 2.11;)
在上面的示例中使用案例类。
final case class Data(id: Int, needed: Int)
val rdd: RDD[Data] = df.as[Data].rdd
val grouped: RDD[(Int, Int)] = rdd.map(d => d.id -> d.needed).reduceByKey { (acc, v) => if (v > 0) acc + 1 else acc }
val result: Array[(Int, Int)] = grouped.collect()
// Array((1,3), (2,0), (3,2))