процентное изменение между ближайшими годами - PullRequest
0 голосов
/ 19 сентября 2018

У меня проблема с созданием новой переменной 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 Pop - 1992 Pop) / 1992 Pop
1997: (2002 Pop - 1997 Pop) / 1997 Pop
1998: (2002 Pop - 1997 Pop) /1997 Pop
1999: (2002 Pop - 1997 Pop) / 1997 Pop
2000: (2002 Pop - 1997 Pop) / 1997 Pop
2001: (2002 Pop - 1997 Pop) / 1997 Pop
2002: (2007 Pop - 2002 Pop) / 2002 Pop
2003: (2007 Pop - 2002 Pop) / 2002 Pop
2004: (2007 Pop - 2002 Pop) / 2002 Pop
2005: (2007 Pop)- 2002 Pop) / 2002 Pop
2006: (2007 Pop - 2002 Pop) / 2002 Pop
2007: (2012 Pop - 2007 Pop) / 2007 Pop
2008: (2012 Pop - 2007 Pop) /2007 Pop

Однако, когда я манипулирую Growth, мне нужно сделать это по столбцу ID.Более того, диапазон года составляет от 1970 до 2018 года, действительно широкий диапазон.Как я могу сделать это в data.table?

Ответы [ 3 ]

0 голосов
/ 20 сентября 2018

Аналогично @calum_you, но с использованием ближайшего 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
0 голосов
/ 20 сентября 2018

Здесь возможен 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]
0 голосов
/ 20 сентября 2018

Не 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

Создано в 2018-09-19 с помощью пакета Представить (v0.2.0).

...