如何使用特定的列顺序计算累积总和?

时间:2021-01-20 19:02:18

标签: r dataframe aggregate

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

<头>
ID SUP 兰德
1 500 1
2 5681 4
3 6514 3
4 25 2
... ... ...

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

<头>
ID SUP 兰德 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,但它做了同样的事情。您对执行此操作的有效方法有什么建议吗?

4 个答案:

答案 0 :(得分:0)

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

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 年 1 月 20 日创建

答案 1 :(得分:0)

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

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))

答案 2 :(得分:0)

1) order 使用末尾注释中的数据并假设您想在不更改行顺序的情况下执行此操作,此基本解决方案定义了排序 {{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

2) sql SQL 具有特定的功能,允许以不同于输入的顺序获取累积和,因此我们可以执行以下操作。请注意,除非我们明确要求,否则 SQL 不保证表的顺序,因此我们在最后使用 o <- order(agfield$RAND) transform(agfield[o, ], cum = cumsum(SUP)) 以确保返回原始顺序——如果返回的顺序不重要,则可以省略它。< /p>

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

答案 3 :(得分:0)

基本的 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))