如何一次计算多个变量和时间点的百分比变化?
How can I calculate percentage changes of multiple variables and time points at once?
使用 dplyr
语法,我正在寻找一种 "elegant" 方法来 mutate
给定数据框的新变量,其中包含不同时间点的百分比变化。
例如,考虑以下 data.frame
包含变量(var.a
、var.b
、var.c
)在不同时间点(A
、 B
).
set.seed(123)
df <- data.frame(replicate(6,sample(1:100,50,rep=TRUE)))
names(df) <- c("A.var.a", "A.var.b", "A.var.c",
"B.var.a", "B.var.b", "B.var.c")
我如何计算每个变量从 A
到 B
的百分比变化,以及 mutate
到数据框 df
的百分比变化?我正在寻找可以在包含更多时间点和变量的更大数据框中实现的 dplyr
或任何其他 "smart" 解决方案,避免逐个输入包含所需输出的新变量。
您可以 tidy 组合起来,然后汇总每一对。像
library(tidyverse)
df %>% tibble::rowid_to_column() %>%
gather(key, value, -rowid) %>%
separate(key, c("time", "var"), extra = "merge") %>% # split "A.var.a" into "A" & "var.a"
arrange(rowid, var, time) %>%
group_by(rowid, var) %>%
summarise(diff = diff(value)/value[1]*100) %>%
spread(var, diff)
# # A tibble: 50 x 4
# # Groups: rowid [50]
# rowid var.a var.b var.c
# * <int> <dbl> <dbl> <dbl>
# 1 1 193.103448 380.00000 -56.66667
# 2 2 -36.708861 115.55556 -32.35294
# 3 3 -4.878049 -23.75000 22.44898
# 4 4 -71.910112 300.00000 -71.87500
# 5 5 -87.368421 -28.07018 10.20408
# 6 6 680.000000 323.80952 -12.22222
# 7 7 9.433962 184.61538 -81.52174
# 8 8 -75.555556 -61.84211 -32.78689
# 9 9 -19.642857 -80.00000 14.28571
# 10 10 -52.173913 -52.63158 480.00000
# # ... with 40 more rows
?
要将列添加到您的原始数据中,您可以将 %>% ungroup() %>% select(-rowid) %>% rename_all(~paste0("perc_", .x)) %>% bind_cols(df)
添加到上面的行中。
或者按照
的思路尝试行向方法
f <- function(x) {
as.list(diff(x, lag=3)/x[1:3]*100)
}
df %>%
rowwise %>%
do(data.frame(perc = f(unlist(.)))
) %>%
bind_cols(df)
# Source: local data frame [50 x 9]
# Groups: <by row>
#
# # A tibble: 50 x 9
# perc.B.var.a perc.B.var.b perc.B.var.c A.var.a A.var.b A.var.c B.var.a B.var.b B.var.c
# <dbl> <dbl> <dbl> <int> <int> <int> <int> <int> <int>
# 1 193.103448 380.00000 -56.66667 29 5 60 85 24 26
# 2 -36.708861 115.55556 -32.35294 79 45 34 50 97 23
# 3 -4.878049 -23.75000 22.44898 41 80 49 39 61 60
# 4 -71.910112 300.00000 -71.87500 89 13 96 25 52 27
# 5 -87.368421 -28.07018 10.20408 95 57 49 12 41 54
# 6 680.000000 323.80952 -12.22222 5 21 90 39 89 79
# 7 9.433962 184.61538 -81.52174 53 13 92 58 37 17
# 8 -75.555556 -61.84211 -32.78689 90 76 61 22 29 41
# 9 -19.642857 -80.00000 14.28571 56 90 42 45 18 48
# 10 -52.173913 -52.63158 480.00000 46 38 15 22 18 87
# # ... with 40 more rows
两者都可能需要一些调整...
使用 dplyr
语法,我正在寻找一种 "elegant" 方法来 mutate
给定数据框的新变量,其中包含不同时间点的百分比变化。
例如,考虑以下 data.frame
包含变量(var.a
、var.b
、var.c
)在不同时间点(A
、 B
).
set.seed(123)
df <- data.frame(replicate(6,sample(1:100,50,rep=TRUE)))
names(df) <- c("A.var.a", "A.var.b", "A.var.c",
"B.var.a", "B.var.b", "B.var.c")
我如何计算每个变量从 A
到 B
的百分比变化,以及 mutate
到数据框 df
的百分比变化?我正在寻找可以在包含更多时间点和变量的更大数据框中实现的 dplyr
或任何其他 "smart" 解决方案,避免逐个输入包含所需输出的新变量。
您可以 tidy 组合起来,然后汇总每一对。像
library(tidyverse)
df %>% tibble::rowid_to_column() %>%
gather(key, value, -rowid) %>%
separate(key, c("time", "var"), extra = "merge") %>% # split "A.var.a" into "A" & "var.a"
arrange(rowid, var, time) %>%
group_by(rowid, var) %>%
summarise(diff = diff(value)/value[1]*100) %>%
spread(var, diff)
# # A tibble: 50 x 4
# # Groups: rowid [50]
# rowid var.a var.b var.c
# * <int> <dbl> <dbl> <dbl>
# 1 1 193.103448 380.00000 -56.66667
# 2 2 -36.708861 115.55556 -32.35294
# 3 3 -4.878049 -23.75000 22.44898
# 4 4 -71.910112 300.00000 -71.87500
# 5 5 -87.368421 -28.07018 10.20408
# 6 6 680.000000 323.80952 -12.22222
# 7 7 9.433962 184.61538 -81.52174
# 8 8 -75.555556 -61.84211 -32.78689
# 9 9 -19.642857 -80.00000 14.28571
# 10 10 -52.173913 -52.63158 480.00000
# # ... with 40 more rows
?
要将列添加到您的原始数据中,您可以将 %>% ungroup() %>% select(-rowid) %>% rename_all(~paste0("perc_", .x)) %>% bind_cols(df)
添加到上面的行中。
或者按照
的思路尝试行向方法 f <- function(x) {
as.list(diff(x, lag=3)/x[1:3]*100)
}
df %>%
rowwise %>%
do(data.frame(perc = f(unlist(.)))
) %>%
bind_cols(df)
# Source: local data frame [50 x 9]
# Groups: <by row>
#
# # A tibble: 50 x 9
# perc.B.var.a perc.B.var.b perc.B.var.c A.var.a A.var.b A.var.c B.var.a B.var.b B.var.c
# <dbl> <dbl> <dbl> <int> <int> <int> <int> <int> <int>
# 1 193.103448 380.00000 -56.66667 29 5 60 85 24 26
# 2 -36.708861 115.55556 -32.35294 79 45 34 50 97 23
# 3 -4.878049 -23.75000 22.44898 41 80 49 39 61 60
# 4 -71.910112 300.00000 -71.87500 89 13 96 25 52 27
# 5 -87.368421 -28.07018 10.20408 95 57 49 12 41 54
# 6 680.000000 323.80952 -12.22222 5 21 90 39 89 79
# 7 9.433962 184.61538 -81.52174 53 13 92 58 37 17
# 8 -75.555556 -61.84211 -32.78689 90 76 61 22 29 41
# 9 -19.642857 -80.00000 14.28571 56 90 42 45 18 48
# 10 -52.173913 -52.63158 480.00000 46 38 15 22 18 87
# # ... with 40 more rows
两者都可能需要一些调整...