我在创建新变量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
中做到这一点?
答案 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