【问题标题】:Spark: Sum of values over all keys?Spark:所有键的值总和?
【发布时间】:2016-02-25 07:06:41
【问题描述】:

假设我有一个键值对,其中包含一个 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)))

我想计算具有属性的所有用户的比例。但是,这种计算要求我可以总结所有的键,我不知道该怎么做。所以我想计算一下:

  1. 有多少用户?

data.size // 4

  1. 有多少用户具有属性 A?

应该是:sum(hasAttrA) / data.size = 3/4 = 0.75

  1. 有多少部分用户具有属性 B?

应该是: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

【问题讨论】:

    标签: scala apache-spark


    【解决方案1】:

    一种可能的解决方案:

    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)
    

    但它的数值属性会更差。

    【讨论】:

    • 我认为这是您可以为这个问题提供的最佳答案。不过,您还没有回答过类似的问题吗?
    • @eliasah 在某些时候看起来都一样 :) 说真的,虽然我找不到任何可以安全地用作骗子的东西。我一直在想这个stackoverflow.com/q/35405314/1560062你有同样的想法吗?
    • 是的,这正是我所考虑的,但我也同意你的观点,在某些时候它们看起来都一样。
    • 如果你认为是我可以删除这个。我考虑过添加一些其他选项,但老实说,这是唯一合理的选择。我的意思是很容易手动编写一个简单的解决方案,但任何强大的选项都需要从头开始重写在线平均值。
    • 我认为保留这个作为答案答案的概括是可以的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-02
    • 1970-01-01
    • 2019-11-11
    • 1970-01-01
    相关资源
    最近更新 更多