首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >按组、ID和日期对R中先前3和5次观察的总和

按组、ID和日期对R中先前3和5次观察的总和
EN

Stack Overflow用户
提问于 2022-11-11 15:19:58
回答 3查看 60关注 0票数 1

我有一个非常大的数据库,看起来像这样。对于cntext,data与其相关的首席执行官(ID)分别向不同的公司提供服务,并且每个首席执行官负责的年份也不同。

代码语言:javascript
复制
ID <- c(1,1,1,1,1,1,3,3,3,5,5,4,4,4,4,4,4,4)
C <- c('a','a','a','a','a','a','b','b','b','b','b','c','c','c','c','c','c','c')
fyear <- c(2000, 2001, 2002,2003,2004,2005,2000, 2001,2002,2003,2004,2000, 2001, 2002,2003,2004,2005,2006)
data <- c(30,50,22,3,6,11,5,3,7,6,9,31,5,6,7,44,33,2)
df1 <- data.frame(ID,C,fyear, data)

ID  C   fyear  data
1   a   2000    30  
1   a   2001    50  
1   a   2002    22  
1   a   2003    3   
1   a   2004    6   
1   a   2005    11  
3   b   2000    5   
3   b   2001    3   
3   b   2002    7   
5   b   2003    6   
5   b   2004    9   
4   c   2000    31  
4   c   2001    5   
4   c   2002    6   
4   c   2003    7   
4   c   2004    44  
4   c   2005    33  
4   c   2006    2       

我需要构建一个代码,它允许我每年总结与每个ID相关的前5和3ID。所以t-3和t-5每年都是。结果是这样的。

代码语言:javascript
复制
ID  C   fyear  data data3data5
1   a   2000    30  NA  NA
1   a   2001    50  NA  NA
1   a   2002    22  102 NA
1   a   2003    3   75  NA
1   a   2004    6   31  111
1   a   2005    11  20  86
3   b   2000    5   NA  NA
3   b   2001    3   NA  NA
3   b   2002    7   15  NA
5   b   2003    6   NA  NA
5   b   2004    9   NA  NA
4   c   2000    31  NA  NA
4   c   2001    5   NA  NA
4   c   2002    6   42  NA
4   c   2003    7   18  NA
4   c   2004    44  57  93
4   c   2005    33  84  95
4   c   2006    2   79  92

我有不同的数据列,我需要执行这个操作,所以如果有人也知道我如何做到这一点,并为我拥有的其他数据列创建一个data3data5列,那就太棒了。但是即使能做我所需要的总结也是很棒的!非常感谢。我环顾四周,似乎找不到任何能满足我需要的类似的cses。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-11-14 20:08:03

我们可以使用rollsumr来执行滚动和。

代码语言:javascript
复制
library(dplyr, exclude = c("filter", "lag"))
library(zoo)

df1 %>%
  group_by(ID, C) %>%
  mutate(data3 = rollsumr(data, 3, fill = NA),
         data5 = rollsumr(data, 5, fill = NA)) %>%
  ungroup
## # A tibble: 18 x 6
##       ID C     fyear  data data3 data5
##    <dbl> <chr> <dbl> <dbl> <dbl> <dbl>
##  1     1 a      2000    30    NA    NA
##  2     1 a      2001    50    NA    NA
##  3     1 a      2002    22   102    NA
##  4     1 a      2003     3    75    NA
##  5     1 a      2004     6    31   111
...snip...

若要将其应用于多列,例如将其应用于use和数据,请使用across

代码语言:javascript
复制
df1 %>%
  group_by(ID, C) %>%
  mutate(across(c("fyear", "data"), 
             list(`3` = ~ rollsumr(., 3, fill = NA), 
                  `5` = ~ rollsumr(., 5, fill = NA)), 
             .names = "{.col}{.fn}")) %>%
  ungroup
## # A tibble: 18 x 8
##       ID C     fyear  data fyear3 fyear5 data3 data5
##    <dbl> <chr> <dbl> <dbl>  <dbl>  <dbl> <dbl> <dbl>
##  1     1 a      2000    30     NA     NA    NA    NA
##  2     1 a      2001    50     NA     NA    NA    NA
##  3     1 a      2002    22   6003     NA   102    NA
##  4     1 a      2003     3   6006     NA    75    NA
##  5     1 a      2004     6   6009  10010    31   111
...snip...
票数 1
EN

Stack Overflow用户

发布于 2022-11-11 16:51:04

为了解决你的具体问题,这是一个有趣的解决方案:

代码语言:javascript
复制
df1 %>% 
  arrange(C, ID, fyear) %>% 
  group_by(C, ID) %>% 
  mutate(
    fyear3=rowSums(list(sapply(1:3, function(x) lag(data, x)))[[1]]),
    fyear5=rowSums(list(sapply(1:5, function(x) lag(data, x)))[[1]])
  ) %>%
  ungroup()
# A tibble: 18 × 6
      ID C     fyear  data fyear3 fyear5
   <dbl> <chr> <dbl> <dbl>  <dbl>  <dbl>
 1     1 a      2000    30     NA     NA
 2     1 a      2001    50     NA     NA
 3     1 a      2002    22     NA     NA
 4     1 a      2003     3    102     NA
 5     1 a      2004     6     75     NA
 6     1 a      2005    11     31    111
 7     3 b      2000     5     NA     NA
 8     3 b      2001     3     NA     NA
 9     3 b      2002     7     NA     NA
10     5 b      2003     6     NA     NA
11     5 b      2004     9     NA     NA
12     4 c      2000    31     NA     NA
13     4 c      2001     5     NA     NA
14     4 c      2002     6     NA     NA
15     4 c      2003     7     42     NA
16     4 c      2004    44     18     NA
17     4 c      2005    33     57     93
18     4 c      2006     2     84     95

第一个变异是有点多毛,所以让我们把其中一个任务分解下来.

查找data列的第n个滞后值,用于n=1、2和3。

代码语言:javascript
复制
sapply(1:3, function(x) lag(data, x))

首席执行官和公司的变更由管道中的group_by()更早地处理。

创建这些滞后值的列表。

代码语言:javascript
复制
list(sapply(1:3, function(x) lag(data, x)))[[1]]

逐行计算滞后值的和。

代码语言:javascript
复制
fyear3=rowSums(list(sapply(1:3, function(x) lag(data, x)))[[1]])

现在概括一下这个问题。编写函数的输入包括数据集(因此它在管道中工作)、新列、包含需要滞后和的值的列以及定义最大滞后值的整数。

代码语言:javascript
复制
lagSum <- function(data, newCol, valueCol, maxLag) {
  data %>% 
    mutate(
      {{newCol}} := rowSums(
                      list(
                        sapply(
                          1:maxLag, 
                          function(x) lag({{valueCol}}, x)
                        )
                      )[[1]]
                    )
    ) %>% 
    ungroup()
}

拥抱({{}})和使用:=是处理tidyverse的非标准评估(NSE)的必要条件。

现在使用这个函数。

代码语言:javascript
复制
df1 %>% 
  arrange(C, ID, fyear) %>% 
  group_by(C, ID) %>% 
  lagSum(sumFYear3, data, 3) %>% 
  lagSum(sumFYear5, data, 5)
# A tibble: 18 × 6
      ID C     fyear  data sumFYear3 sumFYear5
   <dbl> <chr> <dbl> <dbl>     <dbl>     <dbl>
 1     1 a      2000    30        NA        NA
 2     1 a      2001    50        NA        NA
 3     1 a      2002    22        NA        NA
 4     1 a      2003     3       102        NA
 5     1 a      2004     6        75        NA
 6     1 a      2005    11        31       111
 7     3 b      2000     5        NA        92
 8     3 b      2001     3        NA        47
 9     3 b      2002     7        NA        28
10     5 b      2003     6        NA        32
11     5 b      2004     9        NA        32
12     4 c      2000    31        NA        30
13     4 c      2001     5        NA        56
14     4 c      2002     6        NA        58
15     4 c      2003     7        42        57
16     4 c      2004    44        18        58
17     4 c      2005    33        57        93
18     4 c      2006     2        84        95

编辑

我误解了你所说的“滞后”的意思,没有正确地阅读你的描述。我很抱歉。

我认为86data5列的第6行应该是92。如果没有,请解释原因。

得到你想要的答案应该是一个简单的事情,调整我写的函数。例如:

代码语言:javascript
复制
lagSum <- function(data, newCol, valueCol, maxLag) {
  data %>% 
    mutate(
      {{newCol}} := {{valueCol}} + rowSums(
        list(
          sapply(
            1:maxLag, 
            function(x) lag({{valueCol}}, x)
          )
        )[[1]]
      )
    ) %>% 
    mutate() %>%
    ungroup() 
}

给出

代码语言:javascript
复制
df1 %>% 
  arrange(C, ID, fyear) %>% 
  group_by(C, ID) %>% 
  lagSum(sumFYear3, data, 2)
# A tibble: 18 × 5
      ID C     fyear value sumFYear3
   <dbl> <chr> <dbl> <dbl>     <dbl>
 1     1 a      2000    30        NA
 2     1 a      2001    50        NA
 3     1 a      2002    22       102
 4     1 a      2003     3        75
 5     1 a      2004     6        31
 6     1 a      2005    11        20
 7     3 b      2000     5        NA
 8     3 b      2001     3        NA
 9     3 b      2002     7        15
10     5 b      2003     6        NA
11     5 b      2004     9        NA
12     4 c      2000    31        NA
13     4 c      2001     5        NA
14     4 c      2002     6        42
15     4 c      2003     7        18
16     4 c      2004    44        57
17     4 c      2005    33        84
18     4 c      2006     2        79

代码语言:javascript
复制
df1 %>% 
  arrange(C, ID, fyear) %>% 
  group_by(C, ID) %>% 
  lagSum(sumFYear5, data, 4)
# A tibble: 18 × 5
      ID C     fyear  data sumFYear5
   <dbl> <chr> <dbl> <dbl>     <dbl>
 1     1 a      2000    30        NA
 2     1 a      2001    50        NA
 3     1 a      2002    22        NA
 4     1 a      2003     3        NA
 5     1 a      2004     6       111
 6     1 a      2005    11        92
 7     3 b      2000     5        NA
 8     3 b      2001     3        NA
 9     3 b      2002     7        NA
10     5 b      2003     6        NA
11     5 b      2004     9        NA
12     4 c      2000    31        NA
13     4 c      2001     5        NA
14     4 c      2002     6        NA
15     4 c      2003     7        NA
16     4 c      2004    44        93
17     4 c      2005    33        95
18     4 c      2006     2        92

如所料,但是

代码语言:javascript
复制
df1 %>% 
  arrange(C, ID, fyear) %>% 
  group_by(C, ID) %>% 
  lagSum(sumFYear3, data, 2) %>% 
  lagSum(sumFYear5, data, 4)
# A tibble: 18 × 6
      ID C     fyear  data sumFYear3 sumFYear5
   <dbl> <chr> <dbl> <dbl>     <dbl>     <dbl>
 1     1 a      2000    30        NA        NA
 2     1 a      2001    50        NA        NA
 3     1 a      2002    22       102        NA
 4     1 a      2003     3        75        NA
 5     1 a      2004     6        31       111
 6     1 a      2005    11        20        92
 7     3 b      2000     5        NA        47
 8     3 b      2001     3        NA        28
 9     3 b      2002     7        15        32
10     5 b      2003     6        NA        32
11     5 b      2004     9        NA        30
12     4 c      2000    31        NA        56
13     4 c      2001     5        NA        58
14     4 c      2002     6        42        57
15     4 c      2003     7        18        58
16     4 c      2004    44        57        93
17     4 c      2005    33        84        95
18     4 c      2006     2        79        92

不像预期的那样。目前,我无法解释原因。在同一个管道中,我成功地得到了3年和5年的正确答案:

代码语言:javascript
复制
df1 %>% 
  arrange(C, ID, fyear) %>% 
  group_by(C, ID) %>% 
  lagSum(sumFYear3, data, 2) %>% 
  left_join(
    df1 %>% 
      arrange(C, ID, fyear) %>% 
      group_by(C, ID) %>% 
      lagSum(sumFYear5, data, 4)
  )

但这不应该是必要的。我会再想一想,如果我找不到解释的话,我可能会发表自己的一个问题。

或者,这个问题提供了一个使用zoo包的解决方案。

票数 0
EN

Stack Overflow用户

发布于 2022-11-14 13:59:59

我们可以在frollsum中使用data.table

代码语言:javascript
复制
library(data.table)

d <- 2:5

setDT(df1)[
  ,
  c(paste0("data", d)) := lapply(d, frollsum, x = data),
  .(ID, C)
]

产额

代码语言:javascript
复制
> df1
    ID C fyear data data2 data3 data4 data5
 1:  1 a  2000   30    NA    NA    NA    NA
 2:  1 a  2001   50    80    NA    NA    NA
 3:  1 a  2002   22    72   102    NA    NA
 4:  1 a  2003    3    25    75   105    NA
 5:  1 a  2004    6     9    31    81   111
 6:  1 a  2005   11    17    20    42    92
 7:  3 b  2000    5    NA    NA    NA    NA
 8:  3 b  2001    3     8    NA    NA    NA
 9:  3 b  2002    7    10    15    NA    NA
10:  5 b  2003    6    NA    NA    NA    NA
11:  5 b  2004    9    15    NA    NA    NA
12:  4 c  2000   31    NA    NA    NA    NA
13:  4 c  2001    5    36    NA    NA    NA
14:  4 c  2002    6    11    42    NA    NA
15:  4 c  2003    7    13    18    49    NA
16:  4 c  2004   44    51    57    62    93
17:  4 c  2005   33    77    84    90    95
18:  4 c  2006    2    35    79    86    92
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74404619

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档