我需要计算一个值示例的时间" 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]
答案 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 ))
找到这种单线的最佳版本可能是代码高尔夫挑战。