【问题标题】:Divide row value by aggregated sum in R data.frame将行值除以 R data.frame 中的聚合总和
【发布时间】:2017-02-09 19:05:26
【问题描述】:

我有以下数据框

dat <- data.frame(x=c(1,2,3,3,2,1), y=c(3,4,4,5,2,5))

现在我想得到第三列,将 y 行值除以聚合 y 值(基于 x 列中的唯一值)。所以,然后我得到如下第 1 行:1,3,0.375; 0.375 计算为 3 / (5+3)。

我对 R 比较陌生,希望你能帮助我。谢谢!

【问题讨论】:

    标签: r


    【解决方案1】:

    解决这个问题的方法有很多种,这里有一个

    with(dat, ave(y, x, FUN = function(x) x/sum(x)))
    ## [1] 0.3750000 0.6666667 0.4444444 0.5555556 0.3333333 0.6250000
    

    这是另一种可能性

    library(data.table)
    setDT(dat)[, z := y/sum(y), by = x]
    dat
    #    x y         z
    # 1: 1 3 0.3750000
    # 2: 2 4 0.6666667
    # 3: 3 4 0.4444444
    # 4: 3 5 0.5555556
    # 5: 2 2 0.3333333
    # 6: 1 5 0.6250000
    

    这是第三个

    library(dplyr)
    dat %>%
      group_by(x) %>%
      mutate(z = y/sum(y))
    
    # Source: local data frame [6 x 3]
    # Groups: x
    # 
    #   x y         z
    # 1 1 3 0.3750000
    # 2 2 4 0.6666667
    # 3 3 4 0.4444444
    # 4 3 5 0.5555556
    # 5 2 2 0.3333333
    # 6 1 5 0.6250000
    

    【讨论】:

    • with(dat,y/ ave(y,x, FUN=sum)) 会更紧凑一些。另一种选择dat$y/xtabs(y~x, dat)[dat$x]
    • 所以在dplyr 中,sum 对之前的group_by 创建的组求和。试试dat &lt;- data.frame(x=c(1,1,4,4,5,5,6,6), y=c(5,6,1,0,3,1,2,3)) 然后dat %&gt;% group_by(x) %&gt;% group_by(y) %&gt;% mutate(w = y/sum(x)) 看看group_by(x) 没有效果。相反,不分组将整个数据框视为组:dat %&gt;% mutate(w = y/sum(x)) 计算相对权重总和为 1。或者dat %&gt;% mutate(rel_x = x/sum(x)) %&gt;% summarize(total = sum(rel_x)) 应为 1。
    • @DavidTonhofer 你需要什么?
    • @DavidArenburg 谢谢大卫,我很清楚总和,我只是想写一个关于我测试的东西的注释。
    【解决方案2】:

    以下是一些基本的 R 解决方案:

    1) prop.table 像这样使用prop.table 基函数和ave

    transform(dat, z = ave(y, x, FUN = prop.table))
    

    给予:

      x y         z
    1 1 3 0.3750000
    2 2 4 0.6666667
    3 3 4 0.4444444
    4 3 5 0.5555556
    5 2 2 0.3333333
    6 1 5 0.6250000
    

    2) sum 这也有效:

    transform(dat, z = y / ave(y, x, FUN = sum))
    

    【讨论】:

      【解决方案3】:

      当然还有一种方法可以让人们用 SQL 来思考,在这种情况下非常罗嗦,但很好地概括了各种其他类似的问题:

      library(sqldf)
      dat <- sqldf("
        with sums as (
          select
            x
            ,sum(y) as sy
          from dat
          group by x
        )
        select
          d.x
          ,d.y
          ,d.y/s.sy as z
        from dat d
        inner join sums s
          on d.x = s.x
      ")    
      

      【讨论】:

        猜你喜欢
        • 2019-07-21
        • 1970-01-01
        • 1970-01-01
        • 2013-03-23
        • 1970-01-01
        • 2017-01-21
        • 1970-01-01
        • 2015-09-21
        • 1970-01-01
        相关资源
        最近更新 更多