这是我的初始RDD输出
scala> results
scala.collection.Map[String,Long] = Map(4.5 -> 1534824, 0.5 -> 239125, 3.0 -> 4291193, 3.5 -> 2200156, 2.0 -> 1430997, 1.5 -> 279252, 4.0 -> 5561926,
rating -> 1, 1.0 -> 680732, 2.5 -> 883398, 5.0 -> 2898660)
我正在移除一个字符串Key以仅保留数字。
scala> val resultsInt = results.filterKeys(_ != "rating")
resultsInt: scala.collection.Map[String,Long] = Map(4.5 -> 1534824, 0.5 -> 239125, 3.0 -> 4291193, 3.5 -> 2200156, 2.0 -> 1430997, 1.5 -> 279252, 4.0 -> 5561926, 1.0 -> 680732, 2.5 -> 883398, 5.0 -> 2898660)
根据值对RDD进行排序,它给出了预期的输出,但是我希望在排序之前将键从String转换为int以获得一致的输出。
scala> val sortedOut2 = resultsInt.toSeq.sortBy(_._1)
sortedOut2: Seq[(String, Long)] = ArrayBuffer((0.5,239125), (1.0,680732), (1.5,279252), (2.0,1430997), (2.5,883398), (3.0,4291193), (3.5,2200156), (4.0,5561926), (4.5,1534824), (5.0,2898660))
我是Scala的新手,刚开始编写我的Spark程序。请告诉我一些转换Map对象密钥的见解。
答案 0 :(得分:1)
根据您的示例输出,我想您的意思是将密钥转换为Double
?
val results: scala.collection.Map[String, Long] = Map(
"4.5" -> 1534824, "0.5" -> 239125, "3.0" -> 4291193, "3.5" -> 2200156,
"2.0" -> 1430997, "1.5" -> 279252, "4.0" -> 5561926, "rating" -> 1,
"1.0" -> 680732, "2.5" -> 883398, "5.0" -> 2898660
)
results.filterKeys(_ != "rating").
map{ case(k, v) => (k.toDouble, v) }.
toSeq.sortBy(_._1)
res1: Seq[(Double, Long)] = ArrayBuffer((0.5,239125), (1.0,680732), (1.5,279252), (2.0,1430997),
(2.5,883398), (3.0,4291193), (3.5,2200156), (4.0,5561926), (4.5,1534824), (5.0,2898660))
答案 1 :(得分:0)
答案 2 :(得分:0)
请参阅Scala - Convert keys from a Map to lower case?
方法应该类似,
case class row (id: String, value:String)
val rddData = sc.parallelize(Seq(row("1", "hello world"), row("2", "hello there")))
rddData.map{
currentRow => (currentRow.id.toInt, currentRow.value)}
//scala> org.apache.spark.rdd.RDD[(Int, String)]
即使你没有为rdd的结构定义一个case类,你也可以使用类似Tuple2的东西,你可以写
currentRow._1.toInt // instead of currentRow.id.toInt
请研究铸造信息(从String转换为Int),还有几种方法可以解决这个问题
希望这有帮助!祝你好运:)
答案 3 :(得分:0)
如果您尝试过滤掉非数字的密钥,您可以执行以下操作:
import scala.util.{Try,Success,Failure}
(results map { case (k,v) => Try (k.toFloat) match {
case Success(x) => Some((x,v))
case Failure(_) => None
}}).flatten
res1: Iterable[(Float, Long)] = List((4.5,1534824), (0.5,239125), (3.0,4291193), (3.5,2200156), (2.0,1430997), (1.5,279252), (4.0,5561926), (1.0,680732), (2.5,883398), (5.0,2898660))
答案 4 :(得分:0)
将RDD
提取到Map
是合法的,但它首先违背了使用Spark的目的。如果您正在大规模操作,那么您当前的方法会使RDD
无意义。如果你不是,那么你可以像你建议的那样进行Scala集合操作,但那么为什么要费心去处理Spark的开销呢?
我会在DataFrame
抽象级别运行,并将String
列转换为Double
,如下所示:
import sparkSession.implicits._
dataFrame
.select("key", "value")
.withColumn("key", 'key.cast(DoubleType))
这当然是假设在初始数据摄取时将key
设置为Double
后Spark已将inferSchema
识别为true
。