如何计算 R 中多个列的组内百分比变化?
How can I calculate the percentage change within a group for multiple columns in R?
我有一个包含 ID 列和日期列(每个 ID 12 个月)的数据框,并且我有 23 个数字变量。我想获得每个 ID 中按月的百分比变化。我正在使用 quantmod 包以获得百分比变化。
这是一个只有三列的例子(为简单起见):
ID Date V1 V2 V3
1 Jan 2 3 5
1 Feb 3 4 6
1 Mar 7 8 9
2 Jan 1 1 1
2 Feb 2 3 4
2 Mar 7 8 8
我尝试使用 dplyr 和 summarise_each 函数,但没有成功。更具体地说,我尝试了以下方法(train 是数据集的名称):
library(dplyr)
library(quantmod)
group1<-group_by(train,EXAMID)
foo<-function(x){
return(Delt(x))
}
summarise_each(group1,funs(foo))
我也尝试过在 dplyr 中使用 do 函数,但我也没有成功(我猜今晚过得很糟糕!)。
我认为问题出在 Delt 函数上。当我用求和函数替换 Delt 时:
foo<-function(x){
return(sum(x))
}
summarise_each(group1,funs(foo))
结果是每个变量在每个 ID 的日期内求和。那么每个 ID 的百分比如何逐月变化?
使用怎么样
pct <- function(x) x/lag(x)
? (或 (x/lag(x)-1)*100
,或者您希望准确指定 pct change)
例如,
pct(1:3)
[1] NA 2.0 1.5
编辑: 添加 Frank 的建议
pct <- function(x) {x/lag(x)}
dt %>% group_by(ID) %>% mutate_each(funs(pct), c(V1, V2, V3))
ID Date V1 V2 V3
1 Jan NA NA NA
1 Feb 1.500000 1.333333 1.2
1 Mar 2.333333 2.000000 1.5
2 Jan NA NA NA
2 Feb 2.000000 3.000000 4.0
2 Mar 3.500000 2.666667 2.0
您 运行 遇到的问题是因为您的数据未按 "tidy" 方式格式化。您在创建 "wide" 数据框的列中有观察结果 (V1:V3)。 "tidyverse" 最适合长格式。好消息是使用 gather()
函数你可以得到你所需要的。这是使用 "tidyverse".
的解决方案
library(tidyverse)
# Recreate data set
df <- tribble(
~ID, ~Date, ~V1, ~V2, ~V3,
1, "Jan", 2, 3, 5,
1, "Feb", 3, 4, 6,
1, "Mar", 7, 8, 9,
2, "Jan", 1, 1, 1,
2, "Feb", 2, 3, 4,
2, "Mar", 7, 8, 8
)
df
#> # A tibble: 6 × 5
#> ID Date V1 V2 V3
#> <dbl> <chr> <dbl> <dbl> <dbl>
#> 1 1 Jan 2 3 5
#> 2 1 Feb 3 4 6
#> 3 1 Mar 7 8 9
#> 4 2 Jan 1 1 1
#> 5 2 Feb 2 3 4
#> 6 2 Mar 7 8 8
# Gather and calculate percent change
df %>%
gather(key = key, value = value, V1:V3) %>%
group_by(ID, key) %>%
mutate(lag = lag(value)) %>%
mutate(pct.change = (value - lag) / lag)
#> Source: local data frame [18 x 6]
#> Groups: ID, key [6]
#>
#> ID Date key value lag pct.change
#> <dbl> <chr> <chr> <dbl> <dbl> <dbl>
#> 1 1 Jan V1 2 NA NA
#> 2 1 Feb V1 3 2 0.5000000
#> 3 1 Mar V1 7 3 1.3333333
#> 4 2 Jan V1 1 NA NA
#> 5 2 Feb V1 2 1 1.0000000
#> 6 2 Mar V1 7 2 2.5000000
#> 7 1 Jan V2 3 NA NA
#> 8 1 Feb V2 4 3 0.3333333
#> 9 1 Mar V2 8 4 1.0000000
#> 10 2 Jan V2 1 NA NA
#> 11 2 Feb V2 3 1 2.0000000
#> 12 2 Mar V2 8 3 1.6666667
#> 13 1 Jan V3 5 NA NA
#> 14 1 Feb V3 6 5 0.2000000
#> 15 1 Mar V3 9 6 0.5000000
#> 16 2 Jan V3 1 NA NA
#> 17 2 Feb V3 4 1 3.0000000
#> 18 2 Mar V3 8 4 1.0000000
我有一个包含 ID 列和日期列(每个 ID 12 个月)的数据框,并且我有 23 个数字变量。我想获得每个 ID 中按月的百分比变化。我正在使用 quantmod 包以获得百分比变化。
这是一个只有三列的例子(为简单起见):
ID Date V1 V2 V3
1 Jan 2 3 5
1 Feb 3 4 6
1 Mar 7 8 9
2 Jan 1 1 1
2 Feb 2 3 4
2 Mar 7 8 8
我尝试使用 dplyr 和 summarise_each 函数,但没有成功。更具体地说,我尝试了以下方法(train 是数据集的名称):
library(dplyr)
library(quantmod)
group1<-group_by(train,EXAMID)
foo<-function(x){
return(Delt(x))
}
summarise_each(group1,funs(foo))
我也尝试过在 dplyr 中使用 do 函数,但我也没有成功(我猜今晚过得很糟糕!)。
我认为问题出在 Delt 函数上。当我用求和函数替换 Delt 时:
foo<-function(x){
return(sum(x))
}
summarise_each(group1,funs(foo))
结果是每个变量在每个 ID 的日期内求和。那么每个 ID 的百分比如何逐月变化?
使用怎么样
pct <- function(x) x/lag(x)
? (或 (x/lag(x)-1)*100
,或者您希望准确指定 pct change)
例如,
pct(1:3)
[1] NA 2.0 1.5
编辑: 添加 Frank 的建议
pct <- function(x) {x/lag(x)}
dt %>% group_by(ID) %>% mutate_each(funs(pct), c(V1, V2, V3))
ID Date V1 V2 V3
1 Jan NA NA NA
1 Feb 1.500000 1.333333 1.2
1 Mar 2.333333 2.000000 1.5
2 Jan NA NA NA
2 Feb 2.000000 3.000000 4.0
2 Mar 3.500000 2.666667 2.0
您 运行 遇到的问题是因为您的数据未按 "tidy" 方式格式化。您在创建 "wide" 数据框的列中有观察结果 (V1:V3)。 "tidyverse" 最适合长格式。好消息是使用 gather()
函数你可以得到你所需要的。这是使用 "tidyverse".
library(tidyverse)
# Recreate data set
df <- tribble(
~ID, ~Date, ~V1, ~V2, ~V3,
1, "Jan", 2, 3, 5,
1, "Feb", 3, 4, 6,
1, "Mar", 7, 8, 9,
2, "Jan", 1, 1, 1,
2, "Feb", 2, 3, 4,
2, "Mar", 7, 8, 8
)
df
#> # A tibble: 6 × 5
#> ID Date V1 V2 V3
#> <dbl> <chr> <dbl> <dbl> <dbl>
#> 1 1 Jan 2 3 5
#> 2 1 Feb 3 4 6
#> 3 1 Mar 7 8 9
#> 4 2 Jan 1 1 1
#> 5 2 Feb 2 3 4
#> 6 2 Mar 7 8 8
# Gather and calculate percent change
df %>%
gather(key = key, value = value, V1:V3) %>%
group_by(ID, key) %>%
mutate(lag = lag(value)) %>%
mutate(pct.change = (value - lag) / lag)
#> Source: local data frame [18 x 6]
#> Groups: ID, key [6]
#>
#> ID Date key value lag pct.change
#> <dbl> <chr> <chr> <dbl> <dbl> <dbl>
#> 1 1 Jan V1 2 NA NA
#> 2 1 Feb V1 3 2 0.5000000
#> 3 1 Mar V1 7 3 1.3333333
#> 4 2 Jan V1 1 NA NA
#> 5 2 Feb V1 2 1 1.0000000
#> 6 2 Mar V1 7 2 2.5000000
#> 7 1 Jan V2 3 NA NA
#> 8 1 Feb V2 4 3 0.3333333
#> 9 1 Mar V2 8 4 1.0000000
#> 10 2 Jan V2 1 NA NA
#> 11 2 Feb V2 3 1 2.0000000
#> 12 2 Mar V2 8 3 1.6666667
#> 13 1 Jan V3 5 NA NA
#> 14 1 Feb V3 6 5 0.2000000
#> 15 1 Mar V3 9 6 0.5000000
#> 16 2 Jan V3 1 NA NA
#> 17 2 Feb V3 4 1 3.0000000
#> 18 2 Mar V3 8 4 1.0000000