Apache Spark - 生成对列表

时间:2014-10-21 18:22:52

标签: scala mapreduce apache-spark

给定一个包含表格数据的大文件,(V1,V2,...,VN)

2,5
2,8,9
2,5,8
...

我正在尝试使用Spark

获得类似于以下内容的对列表
((2,5),2)
((2,8),2)
((2,9),1)
((8,9),1)
((5,8),1)

我尝试了回复older question时提到的建议,但我遇到了一些问题。例如,

val dataRead = sc.textFile(inputFile)
val itemCounts = dataRead
  .flatMap(line => line.split(","))
  .map(item => (item, 1))
  .reduceByKey((a, b) => a + b)
  .cache()
val nums = itemCounts.keys
  .filter({case (a) => a.length > 0})
  .map(x => x.trim.toInt)
val pairs = nums.flatMap(x => nums2.map(y => (x,y)))

我收到了错误,

scala> val pairs = nums.flatMap(x => nums.map(y => (x,y)))
<console>:27: error: type mismatch;
 found   : org.apache.spark.rdd.RDD[(Int, Int)]
 required: TraversableOnce[?]
       val pairs = nums.flatMap(x => nums.map(y => (x,y)))
                                             ^

有人可以指出我可能做错了什么,或者可能是一个更好的方法来实现同样的目标?非常感谢提前。

4 个答案:

答案 0 :(得分:2)

您可以使用数组的组合方法来实现此目标。

val dataRead = sc.textFile(inputFile)
// "2,5"
// "2,8,9"
// "2,5,8" 
//  ...

val combinations = dataRead.flatMap { line =>
        line.split(",")        // "2,8,9" => Array(2,8,9)
            .combinations(2)   // Iterator
            .toSeq             // ~ Array(Array(2,8), Array(2,9), Array(8,9))
            .map{ case arr => arr(0) -> arr(1) }  // Array((2,8), (2,9), (8,9))
}

// Array((2,5), (2,8), (2,9), (8,9), (2,5), (2,8), (5, 8), ...)

val result = combinations.map(item => item -> 1) // Array(((2,5),1), ((2,9),1), ...)
                         .reduceByKey(_ + _)   
// Array(((2,5),2), ((2,8),2), ((2,9),1), ((8,9),1), ((5,8),1) ....) 
// order may be different.

答案 1 :(得分:1)

我不确定你得到了什么,我用滑动窗口从每一行中提取数字对,例如从2,8,9行我提取2对:(2,8)&amp; (8,9)。如果你需要一些其他的对提取,你需要将slide(2)更新为其他的

  val dataRead = sc.textFile(this.getClass.getResource("/text.txt").getFile)

  // Extract tuples from each line
  val tuples: RDD[(Int, Int)] = dataRead.flatMap(_.split(",").sliding(2)).map {
    case Array(l, r) => (l.toInt, r.toInt)
  }  

  val count = tuples.countByValue()

  count.foreach(println)

输出

((2,5),2)
((8,9),1)
((5,8),1)
((2,8),1)

答案 2 :(得分:1)

基本上,您尝试在(Int, Int)上执行 WordCount 作为键而不是String这是常见示例。

因此,此处的目标是将您的行转换为(Int, Int)元组:

val pairs = sc.textFile(inputFile)
              .map(line => line.split(","))
              .flatMap(a => a.sliding(2))
              .map(a => (a(0).toInt, a(1).toInt) -> 1)
              .reduceByKey(_ + _)

答案 3 :(得分:0)

您可以滑动2个间隔提取单词对。有些句子只能包含一个单词,因此必须在map函数中使用正确的匹配大小写。

Google Drive