我在计算密钥出现次数时遇到了一些麻烦,同时还保留了几个值。
通常我会这样做:
val a = file1.map(x => (x, 1)).reduceByKey(_ + _)
,它给出了每个键的出现次数。
但是,我还希望在计算密钥出现次数的同时保留每次出现密钥的值。像这样:
val a = file1.map(x => (x(1), (x(2), 1)).reduceByKey{case (x,y) => (x._1, y._1, x._2+y._2)}
例如:如果密钥x(1)
是一个国家而x(2)
是一个城市,我想保留一个国家/地区的所有城市,并了解一个国家/地区有多少个城市
答案 0 :(得分:0)
将城市的数量与其列表保持在一起是一件复杂而多余的事情。您可以收集所有城市,并在最后添加尺寸:
使用数据框接口当然更容易(假设数据框为(key:Int, city:String)
)
import org.apache.spark.sql.{ functions => f}
import spark.implicits._
df.groupBy($"key").
agg(f.collect_set($"city").as("cities")).
withColumn("ncities", f.size($"cities"))
但你可以用raw rdd做类似的事情(我在(id,city)
的输入元组中假设)
rdd.map{ x => (x(0),Set(x(1)))}.
reduceByKey{ case(x,y) => x ++ y }.
map { case(x,y:Set[_]) => (x,y, y.size)}
答案 1 :(得分:0)
在这种情况下,我建议使用数据框而不是RDD,并使用groupBy
和agg
方法。
您可以使用toDF
函数轻松将RDD转换为数据框,只需确保先输入含义。假设RDD有两列的示例:
val spark = SparkSession.builder.getOrCreate()
import spark.implicits._
val df = rdd.toDF("country", "city")
然后使用groupBy
并汇总您想要的值。
df.groupBy("country").agg(collect_set($"city").as("cities"), count($"city").as("count"))
答案 2 :(得分:0)
我建议您使用dataframes
以及dataframes
优化且易于使用而不是rdds
。
但是,如果您想了解reduceByKey
功能(例如保留其他信息,如您所说的城市信息),那么您可以执行以下操作
假设您有rdd
val rdd = sc.parallelize(Seq(
("country1", "city1"),
("country1", "city2"),
("country1", "city3"),
("country1", "city3"),
("country2", "city1"),
("country2", "city2")
))
您尝试的reducyByKey
需要进行一些修改
rdd.map(x => (x._1, (Set(x._2), 1))) //I have used Set to get distinct cities (you can use list or arrays or any other collection
.reduceByKey((x,y)=> (x._1 ++ y._1, x._2 + y._2)) //cities are also summed and counts are also summed
应该给你
(country2,(Set(city1, city2),2))
(country1,(Set(city1, city2, city3),4))
我希望答案很有帮助
如果您想详细了解reduceByKey,可以查看我的detailed answer