在我的Spark Scala应用程序中,我具有以下格式的RDD:
(05/05/2020, (name, 1))
(05/05/2020, (name, 1))
(05/05/2020, (name2, 1))
...
(06/05/2020, (name, 1))
我要做的是按日期对这些元素进行分组,并对具有与键相同的“名称”的元组求和。
预期输出:
(05/05/2020, List[(name, 2), (name2, 1)]),
(06/05/2020, List[(name, 1)])
...
为此,我目前正在使用groupByKey
操作和一些额外的转换,以便按键对元组进行分组,并为共享相同元组的元组求和。
出于性能方面的考虑,我想将此groupByKey
操作替换为reduceByKey
或aggregateByKey
,以减少通过网络传输的数据量。
但是,我无法确定如何做到这一点。这两个转换都将值(在本例中为元组)之间的函数作为参数,因此我看不到如何按键对元组进行分组以计算其总和。
这可行吗?
答案 0 :(得分:0)
是的def is_bipartite(v, visited, colors, counter):
visited[v] = True
colors[v] = counter % 2
for u in v.links:
if u in visited:
if colors[v] == colors[u]:
return False # return instead of raise in this base case
if u not in visited:
visited[u] = False
if not is_bipartite(u, visited, colors, counter + 1): # check the recursion
return False # pass on any False
return True # return True only if you got to the end without returning False above
可以按以下方式使用:
.aggeregateBykey()
积分:Best way to merge two maps and sum the values of same key?
答案 1 :(得分:0)
以下是使用reduceByKey
合并元组的方法:
/**
File /path/to/file1:
15/04/2010 name
15/04/2010 name
15/04/2010 name2
15/04/2010 name2
15/04/2010 name3
16/04/2010 name
16/04/2010 name
File /path/to/file2:
15/04/2010 name
15/04/2010 name3
**/
import org.apache.spark.rdd.RDD
val filePaths = Array("/path/to/file1", "/path/to/file2").mkString(",")
val rdd: RDD[(String, (String, Int))] = sc.textFile(filePaths).
map{ line =>
val pair = line.split("\\t", -1)
(pair(0), (pair(1), 1))
}
rdd.
map{ case (k, (n, v)) => (k, Map(n -> v)) }.
reduceByKey{ (acc, m) =>
acc ++ m.map{ case (n, v) => (n -> (acc.getOrElse(n, 0) + v)) }
}.
map(x => (x._1, x._2.toList)).
collect
// res1: Array[(String, List[(String, Int)])] = Array(
// (15/04/2010, List((name,3), (name2,2), (name3,2))), (16/04/2010, List((name,2)))
// )
请注意,由于我们希望将元组合并为Map
中的元素,因此需要初始映射,而对于RDD [K,V],reduceByKey需要相同的数据类型V
转换前后:
def reduceByKey(func: (V, V) => V): RDD[(K, V)]
答案 2 :(得分:0)
您可以将RDD转换为DataFrame,而仅将groupBy与sum一起使用,这是一种实现方法
import org.apache.spark.sql.types._
val schema = StructType(StructField("date", StringType, false) :: StructField("name", StringType, false) :: StructField("value", IntegerType, false) :: Nil)
val rd = sc.parallelize(Seq(("05/05/2020", ("name", 1)),
("05/05/2020", ("name", 1)),
("05/05/2020", ("name2", 1)),
("06/05/2020", ("name", 1))))
val df = spark.createDataFrame(rd.map{ case (a, (b,c)) => Row(a,b,c)},schema)
df.show
+----------+-----+-----+
| date| name|value|
+----------+-----+-----+
|05/05/2020| name| 1|
|05/05/2020| name| 1|
|05/05/2020|name2| 1|
|06/05/2020| name| 1|
+----------+-----+-----+
val sumdf = df.groupBy("date","name").sum("value")
sumdf.show
+----------+-----+----------+
| date| name|sum(value)|
+----------+-----+----------+
|06/05/2020| name| 1|
|05/05/2020| name| 2|
|05/05/2020|name2| 1|
+----------+-----+----------+