最近几年之间的百分比变化

时间:2018-09-19 20:59:46

标签: r data.table data-manipulation

我在创建新变量Growth时遇到问题,该变量等于Population在以“ 2”和“ 7”结尾的最近年份之间的百分比变化。

# dt
ID       Population      year
1                50      1995
1                60      1996
1                70      1997
1                80      1998
1                90      1999
1               100      2000
1               105      2001
1               110      2002
1               120      2003
1               130      2004
1               140      2005
1               150      2006
1               200      2007
1               300      2008

dt <- data.table::fread("ID       Population      year
1                50      1995
  1                60      1996
  1                70      1997
  1                80      1998
  1                90      1999
  1               100      2000
  1               105      2001
  1               110      2002
  1               120      2003
  1               130      2004
  1               140      2005
  1               150      2006
  1               200      2007
  1               300      2008", header = T)

增长=最近的年份(以“ 2”和“ 7”结尾)之间的流行率变化百分比。例如,在年份:
1996年:(1997年流行音乐– 1992年流行音乐)/ 1992年流行音乐
1997:(2002年流行音乐– 1997年流行音乐)/ 1997年流行音乐
1998年:(2002年流行音乐– 1997年流行音乐)/ 1997年流行音乐
1999:(2002年流行音乐– 1997年流行音乐)/ 1997年流行音乐
2000年:(2002年流行音乐– 1997年流行音乐)/ 1997年流行音乐
2001:(2002 Pop – 1997 Pop)/ 1997 Pop
2002年:( 2007年流行音乐– 2002年流行音乐)/ 2002年流行音乐
2003年:( 2007年流行音乐– 2002年流行音乐)/ 2002年流行音乐
2004年:( 2007年流行音乐– 2002年流行音乐)/ 2002年流行音乐
2005年:( 2007年流行音乐– 2002年流行音乐)/ 2002年流行音乐
2006年:( 2007年流行音乐– 2002年流行音乐)/ 2002年流行音乐
2007年:(2012年流行音乐– 2007年流行音乐)/ 2007年流行音乐
2008年:(2012年流行音乐– 2007年流行音乐)/ 2007年流行音乐

但是,当我操作Growth时,需要按ID列进行操作。而且,一年的范围是从1970年到2018年,范围确实很大。如何在data.table中做到这一点?

3 个答案:

答案 0 :(得分:2)

这是一种可能的data.table方法:

#calculate the 5-yearly percentage changes first by 
#i) first creating all combinations of ID and 5-yearly years
#2) then join with the original dataset 
#3) then leading the Population column and calculating Growth
pctChange <- dt[CJ(ID=ID, year=seq(1967, 2022, 5), unique=TRUE), 
    .(ID, year, Growth=(shift(Population, type="lead") - Population) / Population), 
    on=.(ID, year)]    

#then perform a rolling join (`roll=TRUE`; see ?data.table) and 
#then update the original dt with Growth by reference (i.e. `:=`)
dt[, Growth := pctChange[dt, Growth, on=.(ID, year), roll=TRUE]]
dt

输出:

    ID Population year    Growth
 1:  1         50 1995        NA
 2:  1         60 1996        NA
 3:  1         70 1997 0.5714286
 4:  1         80 1998 0.5714286
 5:  1         90 1999 0.5714286
 6:  1        100 2000 0.5714286
 7:  1        105 2001 0.5714286
 8:  1        110 2002 0.8181818
 9:  1        120 2003 0.8181818
10:  1        130 2004 0.8181818
11:  1        140 2005 0.8181818
12:  1        150 2006 0.8181818
13:  1        200 2007        NA
14:  1        300 2008        NA

注意事项:滚动联接似乎不适用于更新联接

dt[pctChange, Growth := Growth, on=.(ID, year), roll=TRUE]

答案 1 :(得分:1)

这不是data.table解决方案,但是您可以在tidyverse中这样做,这可能会给您一些想法。基本上,使用整数除法%/%计算要与每一行进行比较的年份,然后将表连接到自身上,以便在每一行中都有比较值。然后,使用您的公式来计算增长很简单。

library(tidyverse)
dt <- read_table("ID       Population      year
1                50      1995
1                60      1996
1                70      1997
1                80      1998
1                90      1999
1               100      2000
1               105      2001
1               110      2002
1               120      2003
1               130      2004
1               140      2005
1               150      2006
1               200      2007
1               300      2008")
dt %>%
  mutate(compare_year = 5 * year %/% 5 - 3) %>%
  left_join(dt, by = c("ID", "compare_year" = "year")) %>%
  mutate(growth = (Population.x - Population.y) / Population.y)
#> # A tibble: 14 x 6
#>       ID Population.x  year compare_year Population.y growth
#>    <int>        <int> <int>        <dbl>        <int>  <dbl>
#>  1     1           50  1995         1992           NA NA    
#>  2     1           60  1996         1992           NA NA    
#>  3     1           70  1997         1992           NA NA    
#>  4     1           80  1998         1992           NA NA    
#>  5     1           90  1999         1992           NA NA    
#>  6     1          100  2000         1997           70  0.429
#>  7     1          105  2001         1997           70  0.5  
#>  8     1          110  2002         1997           70  0.571
#>  9     1          120  2003         1997           70  0.714
#> 10     1          130  2004         1997           70  0.857
#> 11     1          140  2005         2002          110  0.273
#> 12     1          150  2006         2002          110  0.364
#> 13     1          200  2007         2002          110  0.818
#> 14     1          300  2008         2002          110  1.73

reprex package(v0.2.0)于2018-09-19创建。

答案 2 :(得分:1)

类似于@calum_you,但使用OP中要求的最近5年增长。

样本数据

dt <- data.table::fread("ID       Population      year
1                50      1995
  1                60      1996
  1                70      1997
  1                80      1998
  1                90      1999
  1               100      2000
  1               105      2001
  1               110      2002
  1               120      2003
  1               130      2004
  1               140      2005
  1               150      2006
  1               200      2007
  1               300      2008", header = T) %>%
  as_data_frame()  

1)5年增长率表

dt_5yr <- dt %>% 
  filter(year %% 10 %in% c(2,7)) %>%
  group_by(ID) %>%   # I assume there will be more IDs in full data
  mutate(growth_5yr = Population / lag(Population) - 1) %>%
  ungroup()

2)将原始表格加入5年增长率

dt %>%
  mutate(join_yr = year + 5 - (year + 3) %% 5) %>%
  left_join(dt_5yr %>% select(join_yr = year, growth_5yr))

输出

   ID Population year join_yr growth_5yr
1   1         50 1995    1997         NA
2   1         60 1996    1997         NA
3   1         70 1997    2002  0.5714286
4   1         80 1998    2002  0.5714286
5   1         90 1999    2002  0.5714286
6   1        100 2000    2002  0.5714286
7   1        105 2001    2002  0.5714286
8   1        110 2002    2007  0.8181818
9   1        120 2003    2007  0.8181818
10  1        130 2004    2007  0.8181818
11  1        140 2005    2007  0.8181818
12  1        150 2006    2007  0.8181818
13  1        200 2007    2012         NA
14  1        300 2008    2012         NA