假设我有包含userId的键值对,以及表示用户具有属性的布尔整数列表:
userId hasAttrA hasAttrB hasAttrC
joe 1 0 1
jack 1 1 0
jane 0 0 1
jeri 1 0 0
在Scala代码中,数据结构如下所示:
var data = Array(("joe", List(1, 0, 1)),
("jack", List(1, 1, 0)),
("jane", List(0, 0, 1)),
("jeri", List(1, 0, 0)))
我想计算具有这些属性的所有用户的比例。但是,这个计算要求我可以总结所有的键,我不知道该怎么做。所以我想计算:
data.size // 4
应该是:sum(hasAttrA)/ data.size = 3/4 = 0.75
应该是:sum(hasAttrB)/ data.size = 1/4 = 0.25
等
如何计算所有键的总和,以及如何计算最终百分比?
编辑2016年2月24日:
我可以手动查找各列的总和,如下所示:
var sumAttributeA = data.map{ case(id, attributeList) => attributeList(0)}.sum
var sumAttributeB = data.map{ case(id, attributeList) => attributeList(1)}.sum
var sumAttributeC = data.map{ case(id, attributeList) => attributeList(2)}.sum
var fractionAttributeA = sumAttributeA.toDouble/data.size
//fractionAttributeA: Double = 0.75
var fractionAttributeB = sumAttributeB.toDouble/data.size
//fractionAttributeB: Double = 0.25
答案 0 :(得分:2)
一种可能的解决方案:
import org.apache.spark.mllib.stat.MultivariateOnlineSummarizer
import org.apache.spark.mllib.linalg.Vectors
val stats = sc.parallelize(data)
.values
.map(xs => Vectors.dense(xs.toArray.map(_.toDouble)))
.aggregate(new MultivariateOnlineSummarizer)(_ add _, _ merge _)
(stats.count, stats.mean)
// (Long, org.apache.spark.mllib.linalg.Vector) = (4,[0.75,0.25,0.5])
您也可以手动应用类似的操作:
val (total, sums) = sc.parallelize(data).values
.map(vs => (1L, vs.map(_.toLong)))
.reduce{
case ((cnt1, vs1), (cnt2, vs2)) =>
(cnt1 + cnt2, vs1.zip(vs2).map{case (x, y) => x + y})}
sums.map(_.toDouble / total)
但它会有更糟糕的数字属性。