Spark Scala总结数据集的列元素?

时间:2015-07-24 12:02:19

标签: scala count apache-spark

我需要计算一个值示例的时间" 2"正在每一栏中发生。

我的数据集具有以下结构:

1 1 2 0 0 0 2 
0 2 0 1 1 1 1
1 2 1 0 2 2 2
0 0 0 0 1 1 2

我导入了文件:

val ip = sc.textFile("/home/../data-scala.txt").map(line => line.split(" "))

如何总结等于" 2"在每一栏?我期望得到一个元素数组

[0,2,1,0,1,1,3]

2 个答案:

答案 0 :(得分:3)

这样的事情怎么样:

import breeze.linalg.DenseVector

def toInd(s: String): DenseVector[Int] = {
    DenseVector[Int](s.split(" ").map(x => if(x == "2") 1 else 0))
}

sc.textFile("/path/to/file").map(toInd).reduce(_ + _)

如果您期望总和等于零的大量列,则可以将DenseVector替换为SparseVector

上述解决方案需要为RDD的每个元素提供一个新的DenseVector对象。出于性能原因,您可以考虑使用aggregate和向量变异:

def seqOp(acc: DenseVector[Int] , cols: Array[String]): DenseVector[Int] = {
    cols.zipWithIndex.foreach{ case (x, i) => if(x == "2") acc(i) += 1}
    acc
}

def combOp(acc1: DenseVector[Int], acc2: DenseVector[Int]): DenseVector[Int] = {
    acc1 += acc2
    acc1
}

val n = ip.first.length
ip.aggregate(DenseVector.zeros[Int](n))(seqOp, combOp)

如果需要,您可以轻松地将DenseVector替换为稀疏的scala.collection.mutable.Map

如果你问我这是相当丑陋的,所以我提供它只是为了让答案完整。

答案 1 :(得分:2)

您可以map先在每个位置2存在,为您提供

[ 0 0 1 0 0 0 1 ]
[ 0 1 0 0 0 0 0 ]
[ 0 1 0 0 1 1 1 ]
[ 0 0 0 0 0 0 1 ]

然后只需逐渐减少以逐列SUM。

不涉及Spark,它看起来像:

val list = Seq(
  Seq(1, 1, 2, 0, 0, 0, 2),
  Seq(0, 2, 0, 1, 1, 1, 1),
  Seq(1, 2, 1, 0, 2, 2, 2),
  Seq(0, 0, 0, 0, 1, 1, 2)
)

list.
   map(_.map(v => if(v == 2) 1 else 0)).
   reduce((a,b) => a.zip(b).map(t => t._1 +t._2 ))

找到这种单线的最佳版本可能是代码高尔夫挑战。