在rdd级别具有groupby的条件运算符-Scala

时间:2018-11-25 22:52:13

标签: scala apache-spark rdd

我正在使用Spark 1.60Scala 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级的。任何获得我想要的输出的帮助都会很棒。

2 个答案:

答案 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))