0

我正在使用如下所示的数据集处理 R:

数据集的屏幕截图

test=data.frame("1991" = c(1,5,3), "1992" = c(4,3,3), "1993" = c(10,5,3), "1994" = c(1,1,1), "1995" = c(2,2,6))
test=plyr::rename(test, c("X1991"="1991", "X1992"="1992", "X1993"="1993", "X1994"="1994", "X1995"="1995"))

我想要做的是我想创建名为 Pre1991, Pre1992, Pre1993, ... 的变量,这些变量将存储该年的累积值,例如

Pre1991 = test$1991
Pre1992 = test$1991 + test$1992
Pre1993 = test$1991 + test$1992 + test$1993 

很快。

我的真实数据集包含 1900-2017 年的变量,因此我无法手动执行此操作。我想写一个for循环,但它没有用。

for (i in 1900:2017){
  x = paste0("Pre",i)
  df[[x]] = rowSums(df[,(colnames(df)<=i)]) 
}

有人可以帮忙查看我的代码/建议其他方法吗?谢谢!

编辑1:

非常感谢!我想知道是否有办法可以反向使用 cumsum 函数?例如,如果我对特定年份之后发生的事情感兴趣:

Post1991 = test$1992 + test$1993 + test$1994 + test$1995 + ...
Post1992 = test$1993 + test$1994 + test$1995 + ...
Post1993 = test$1994 + test$1995 + ...
4

3 回答 3

2

使用tidyverse我们可以在再次传播之前收集和计算。为此,需要安排数据。

library(tidyverse)
test <- data.frame("1991" = c(1, 5, 3),
                   "1992" = c(4, 3, 3),
                   "1993" = c(10, 5, 3),
                   "1994" = c(1, 1, 1),
                   "1995" = c(2, 2, 6))
test <- plyr::rename(test, c("X1991" = "1991",
                             "X1992" = "1992",
                             "X1993" = "1993",
                             "X1994" = "1994",
                             "X1995" = "1995"))

前锋

test %>%
  mutate(id = 1:nrow(.)) %>% # adding an ID to identify groups
  gather(year, value, -id) %>% # wide to long format
  arrange(id, year) %>%
  group_by(id) %>%
  mutate(value = cumsum(value)) %>% 
  ungroup() %>%
  spread(year, value) %>%  # long to wide format
  select(-id) %>%
  setNames(paste0("pre", names(.))) # add prefix to columns

##  A tibble: 3 x 5
#   pre1991 pre1992 pre1993 pre1994 pre1995
#     <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
# 1      1.      5.     15.     16.     18.
# 2      5.      8.     13.     14.     16.
# 3      3.      6.      9.     10.     16.

反向

正如您的定义所指定的它不是严格的相反顺序,它的相反顺序不包括它自己,这将是累积滞后总和。

test %>%
  mutate(id = 1:nrow(.)) %>%
  gather(year, value, -id) %>%
  arrange(id, desc(year)) %>% # using desc() to reverse sorting
  group_by(id) %>%
  mutate(value = cumsum(lag(value, default = 0))) %>% # lag cumsum
  ungroup() %>%
  spread(year, value) %>%
  select(-id) %>%
  setNames(paste0("post", names(.)))


## A tibble: 3 x 5
#   post1991 post1992 post1993 post1994 post1995
#      <dbl>    <dbl>    <dbl>    <dbl>    <dbl>
# 1      17.      13.       3.       2.       0.
# 2      11.       8.       3.       2.       0.
# 3      13.      10.       7.       6.       0.

于 2018-04-21T02:07:38.340 回答
2

这有点低效,因为它正在从 a 转换data.frame为 amatrix并返回,但是......

as.data.frame(t(apply(as.matrix(test), 1, cumsum)))
#   1991 1992 1993 1994 1995
# 1    1    5   15   16   18
# 2    5    8   13   14   16
# 3    3    6    9   10   16

如果您的数据有其他不基于年份的列,例如

test$quux <- LETTERS[3:5]
test
#   1991 1992 1993 1994 1995 quux
# 1    1    4   10    1    2    C
# 2    5    3    5    1    2    D
# 3    3    3    3    1    6    E

然后在两边子集:

test[1:5] <- as.data.frame(t(apply(as.matrix(test[1:5]), 1, cumsum)))
test
#   1991 1992 1993 1994 1995 quux
# 1    1    5   15   16   18    C
# 2    5    8   13   14   16    D
# 3    3    6    9   10   16    E

编辑

相反,只需使用重复rev

as.data.frame(t(apply(as.matrix(test), 1, function(a) rev(cumsum(rev(a)))-a)))
#   1991 1992 1993 1994 1995
# 1   17   13    3    2    0
# 2   11    8    3    2    0
# 3   13   10    7    6    0
于 2018-04-21T01:58:23.267 回答
1

我们可以rowCumsums使用matrixStats

library(matrixStats)
test[] <- rowCumsums(as.matrix(test))
test
#  1991 1992 1993 1994 1995
#1    1    5   15   16   18
#2    5    8   13   14   16
#3    3    6    9   10   16
于 2018-04-21T03:02:01.080 回答