【问题标题】:How to calculate cumulative sum using a specific column order?如何使用特定的列顺序计算累积和?
【发布时间】:2021-04-25 04:42:43
【问题描述】:

我有一个数据集,我想在其中计算 R 中的累积和。我的数据名称示例agfield

ID SUP RAND
1 500 1
2 5681 4
3 6514 3
4 25 2
... ... ...

基本上,我想使用 RAND 列的顺序计算 csum 列中 SUP 列的累积和。 预期结果:

ID SUP RAND csum
1 500 1 500
2 5681 4 12720
3 6514 3 7039
4 25 2 525
... ... ... ...

我在这里查看了有关此主题的其他几个问题/答案,但我可以得到一个遵循 RAND 列顺序的结果。 我尝试使用agfield$csum<-ave(agfield$SUP, agfield$RAND, FUN=cumsum),但它只给了我 SUP 号码并且不做累计和。 我也尝试使用 group_by,但它做了同样的事情。您对执行此操作的有效方法有什么建议吗?

【问题讨论】:

    标签: r dataframe aggregate


    【解决方案1】:

    我认为如果你重新排列你的行,这可能会成为一个很容易的问题

    library(tidyverse)
    
    df_example <- tibble::tribble(
      ~ID,  ~SUP, ~RAND,
       1L,  500L,    1L,
       2L, 5681L,    4L,
       3L, 6514L,    3L,
       3L,   25L,    1L
      )
    
    df_example %>% 
      arrange(RAND,ID) %>% 
      mutate(csum = cumsum(SUP))
    #> # A tibble: 4 x 4
    #>      ID   SUP  RAND  csum
    #>   <int> <int> <int> <int>
    #> 1     1   500     1   500
    #> 2     3    25     1   525
    #> 3     3  6514     3  7039
    #> 4     2  5681     4 12720
    

    reprex package (v0.3.0) 于 2021-01-20 创建

    【讨论】:

      【解决方案2】:

      一种选择是创建一个临时的额外列来存储数据的初始顺序,然后计算累积和。然后我们可以将其放回初始顺序并删除临时列。

      library(dplyr)
      agfield %>%
        mutate(INITORDER = row_number()) %>%
        arrange(RAND,INITORDER) %>%
        mutate(csum = cumsum(SUP)) %>%
        arrange(INITORDER) %>%
        dplyr::select(-INITORDER)
        ID  SUP RAND  csum
      1  1  500    1   500
      2  2 5681    4 12720
      3  3 6514    3  7039
      4  3   25    1   525
      

      样本数据:

      agfield <- structure(list(ID = c(1L, 2L, 3L, 3L), SUP = c(500L, 5681L, 6514L, 
      25L), RAND = c(1L, 4L, 3L, 1L)), class = "data.frame", row.names = c(NA, 
      -4L))
      

      【讨论】:

        【解决方案3】:

        1) 顺序 使用末尾注释中的数据并假设您想在不更改行顺序的情况下执行此操作,此基本解决方案定义了排序 SUP 的排列作为o,将其应用于SUP,取其中的cumsum,然后通过应用逆序将其恢复为原始顺序,即order(o)

        o <- order(agfield$RAND)
        transform(agfield, cum = cumsum(SUP[o])[order(o)])
        

        给予:

          ID  SUP RAND  csum
        1  1  500    1   500
        2  2 5681    4 12720
        3  3 6514    3  7039
        4  3   25    1   525
        

        这是一个演示,表明逆序确实是上面显示的表达式。

        set.seed(123)
        x <- rnorm(1000)
        o <- order(x)
        identical(x, x[o][order(o)])
        ## [1] TRUE
        

        如果对数据框进行排序是可以接受的,那么我们可以这样做,这会稍微短一些。

        o <- order(agfield$RAND)
        transform(agfield[o, ], cum = cumsum(SUP))
        

        2) sql SQL 具有允许以不同于输入的顺序获取累积总和的特定功能,因此我们可以执行以下操作。请注意,除非我们明确要求,否则 SQL 不保证表的顺序,因此我们在末尾使用 order by rowid 以确保返回原始顺序 - 如果返回的顺序不重要,则可以省略它。

        library(sqldf)
        sqldf("select ID, SUP, RAND, sum(SUP) over (order by RAND, rowid) csum 
          from agfield
          order by rowid")
        

        给予:

          ID  SUP RAND  csum
        1  1  500    1   500
        2  2 5681    4 12720
        3  3 6514    3  7039
        4  3   25    1   525
        

        注意

        Lines <- "
        ID SUP RAND
        1 500 1
        2 5681 4
        3 6514 3
        3 25 1"
        agfield <- read.table(text = Lines, header = TRUE)
        

        【讨论】:

        • 嗨,谢谢你的详细解释,它真的帮助我理解。我已经为我的数据集应用了这个代码,它终于可以工作了。感谢您的帮助!
        【解决方案4】:

        基本 R 选项

        transform(
          agfield,
          csum = cumsum(SUP[RAND])[RAND]
        )
        

        给予

          ID  SUP RAND  csum
        1  1  500    1   500
        2  2 5681    4 12720
        3  3 6514    3  7039
        4  3   25    2   525
        

        数据

        > dput(agfield)
        structure(list(ID = c(1L, 2L, 3L, 3L), SUP = c(500L, 5681L, 6514L, 
        25L), RAND = c(1L, 4L, 3L, 2L)), class = "data.frame", row.names = c(NA,
        -4L))
        

        【讨论】:

        • 您好,感谢您的回复。我认为它会起作用,但在我的完整数据集中有负数,当我尝试你的代码时,我收到一条与负数相关的错误消息。
        • @cdes 哪一列有负数?
        • 真实数据集中的RAND列包含负值
        猜你喜欢
        • 2016-05-11
        • 1970-01-01
        • 2020-12-17
        • 2023-01-18
        • 2021-05-11
        • 2020-11-04
        • 2016-07-23
        • 2021-07-27
        • 2020-09-26
        相关资源
        最近更新 更多