【问题标题】:percentage change between closest years最近年份之间的百分比变化
【发布时间】:2019-02-24 02:49:38
【问题描述】:

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

# 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 年流行音乐 – 1997 年流行音乐)/ 1997 年流行音乐
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 中做到这一点?

【问题讨论】:

  • 在您的示例中,1992 Pop 不存在,那么您将如何计算 1996 的 Growth? 2012 流行音乐也不存在

标签: r data.table data-manipulation


【解决方案1】:

这是一种可能的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]

【讨论】:

  • 太棒了。如果我想被ID操作怎么办?在on = .(ID, year) 中添加ID?不确定
  • 谢谢。上面CJ的功能是什么?
  • 它是来自data.table 的交叉连接函数。您可能想查看?data.table::CJ
【解决方案2】:

不是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 年 9 月 19 日创建。

【讨论】:

    【解决方案3】:

    类似于@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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多