让 dplyr 变异使用公式
Let dplyr mutate use formula
我有一个大型数据集存储在一个长数据框中。我想提取一些变量的数据并使用公式生成新数据。应从公式中提取所有必要的信息。首先,我想使用公式中的信息为相应的变量过滤数据集 - 我为此使用 all.vars()
函数。我还依赖于 CRAN 上的 formula.tools
包。它用于轻松提取等式的左侧和右侧(分别为 lhs
和 rhs
)。
library(dplyr)
library(reshape2)
library(formula.tools)
set.seed(100)
the_data <- data.frame(country = c(rep("USA", 9), rep("DEU", 9), rep("CHN", 9)),
year = c(2000, 2010, 2020),
variable = c(rep("GDP", 3), rep("Population", 3), rep("Consumption", 3)),
value = rnorm(27, 100, 100))
add_variable <- function(df, equation){
df <- filter(df, variable %in% all.vars(equation))
df <- dcast(df, country + year ~ variable)
df <- mutate_(df, rhs(equation))
# code to keep only the newly generated column
# ...
df <- melt(df, id.vars = c("country", "year"))
}
result <- add_variable(the_data, GDPpC ~ GDP / Population)
新生成的列应命名为GDPpC
,当前名称为GDP/Population
。如何改进?在最后一步中,我还想过滤数据,以便结果中只包含新生成的数据,然后可以通过 rbind
.
将其附加到源数据帧
这会是一个解决方案吗?
add_variable <- function(df, equation){
df <- filter(df, variable %in% all.vars(equation))
orig_vars <- unique(df$variable)
df <- dcast(df, country + year ~ variable)
df <- mutate_(df, rhs(equation))
colnames(df)[ncol(df)] <- as.character(lhs(equation))
df <- melt(df, id.vars = c("country", "year"))
df <- filter(df, !variable%in%orig_vars)
}
result <- add_variable(the_data, GDPpC ~ GDP / Population)
result
country year variable value
1 CHN 2000 GDPpC 0.04885649
2 CHN 2010 GDPpC 2.62313658
3 CHN 2020 GDPpC 0.31685382
4 DEU 2000 GDPpC 0.80180998
5 DEU 2010 GDPpC 0.62642877
6 DEU 2020 GDPpC 0.97587188
7 USA 2000 GDPpC 0.26383912
8 USA 2010 GDPpC 1.01303516
9 USA 2020 GDPpC 0.69851501
多年后我在寻找有关在 dplyr::mutate
中使用公式的信息时来到这里,因为我经常发现它更加简洁明了。 dplyr
当然自 2016 年以来已经发展和变化,包括 transmute
现在已被弃用的事实。但好消息是,如果您愿意使用 formula.tools
,解决方案将非常简洁。如下图。
library(dplyr)
# reproducible play_data
set.seed(2020)
play_data <-
data.frame(
a = runif(20, 0.01, .5),
b = runif(20, 0.02, .5),
c = runif(20, 0.03, .5),
d = runif(20, 0.04, .5),
e = runif(20,1,5),
f = runif(20,10,50)
)
my_formula <- newvariable ~ a * b^c / d * log(e) - f
require(formula.tools)
mutate_by_formula <- function(df, equation){
df %>% transmute( !!lhs(equation) := !!rhs(equation) )
}
mutate_by_formula(play_data, my_formula)
#> newvariable
#> 1 -25.80405
#> 2 -20.48974
#> 3 -37.87361
#> 4 -46.52231
#> 5 -19.88420
#> 6 -16.49153
#> 7 -37.25498
#> 8 -41.02025
#> 9 -31.88338
#> 10 -42.17896
#> 11 -30.75905
#> 12 -10.42447
#> 13 -25.84538
#> 14 -46.08206
#> 15 -13.51940
#> 16 -25.30124
#> 17 -19.80536
#> 18 -26.42881
#> 19 -38.02190
#> 20 -30.51113
至于 OP 的原始示例和细节,它稍微复杂一些,因为必须对数据进行整形,但基本概念是相同的。唯一的转折是 dcast
和最后的 select
以删除计算中使用的变量。
library(dplyr)
library(reshape2)
library(formula.tools)
set.seed(100)
the_data <- data.frame(country = c(rep("USA", 9), rep("DEU", 9), rep("CHN", 9)),
year = c(2000, 2010, 2020),
variable = c(rep("GDP", 3), rep("Population", 3), rep("Consumption", 3)),
value = rnorm(27, 100, 100))
specific_function <- function(df, equation){
df %>%
filter(variable %in% all.vars(equation)) %>%
dcast(country + year ~ variable) %>%
mutate(!!lhs(equation) := !!rhs(equation)) %>%
select(-all.vars(equation)[2:length(all.vars(equation))])
}
specific_function(the_data, GDPpC ~ GDP / Population)
#> country year GDPpC
#> 1 CHN 2000 0.04885649
#> 2 CHN 2010 2.62313658
#> 3 CHN 2020 0.31685382
#> 4 DEU 2000 0.80180998
#> 5 DEU 2010 0.62642877
#> 6 DEU 2020 0.97587188
#> 7 USA 2000 0.26383912
#> 8 USA 2010 1.01303516
#> 9 USA 2020 0.69851501
由 reprex package (v0.3.0)
于 2020-05-04 创建
我有一个大型数据集存储在一个长数据框中。我想提取一些变量的数据并使用公式生成新数据。应从公式中提取所有必要的信息。首先,我想使用公式中的信息为相应的变量过滤数据集 - 我为此使用 all.vars()
函数。我还依赖于 CRAN 上的 formula.tools
包。它用于轻松提取等式的左侧和右侧(分别为 lhs
和 rhs
)。
library(dplyr)
library(reshape2)
library(formula.tools)
set.seed(100)
the_data <- data.frame(country = c(rep("USA", 9), rep("DEU", 9), rep("CHN", 9)),
year = c(2000, 2010, 2020),
variable = c(rep("GDP", 3), rep("Population", 3), rep("Consumption", 3)),
value = rnorm(27, 100, 100))
add_variable <- function(df, equation){
df <- filter(df, variable %in% all.vars(equation))
df <- dcast(df, country + year ~ variable)
df <- mutate_(df, rhs(equation))
# code to keep only the newly generated column
# ...
df <- melt(df, id.vars = c("country", "year"))
}
result <- add_variable(the_data, GDPpC ~ GDP / Population)
新生成的列应命名为GDPpC
,当前名称为GDP/Population
。如何改进?在最后一步中,我还想过滤数据,以便结果中只包含新生成的数据,然后可以通过 rbind
.
这会是一个解决方案吗?
add_variable <- function(df, equation){
df <- filter(df, variable %in% all.vars(equation))
orig_vars <- unique(df$variable)
df <- dcast(df, country + year ~ variable)
df <- mutate_(df, rhs(equation))
colnames(df)[ncol(df)] <- as.character(lhs(equation))
df <- melt(df, id.vars = c("country", "year"))
df <- filter(df, !variable%in%orig_vars)
}
result <- add_variable(the_data, GDPpC ~ GDP / Population)
result
country year variable value
1 CHN 2000 GDPpC 0.04885649
2 CHN 2010 GDPpC 2.62313658
3 CHN 2020 GDPpC 0.31685382
4 DEU 2000 GDPpC 0.80180998
5 DEU 2010 GDPpC 0.62642877
6 DEU 2020 GDPpC 0.97587188
7 USA 2000 GDPpC 0.26383912
8 USA 2010 GDPpC 1.01303516
9 USA 2020 GDPpC 0.69851501
多年后我在寻找有关在 dplyr::mutate
中使用公式的信息时来到这里,因为我经常发现它更加简洁明了。 dplyr
当然自 2016 年以来已经发展和变化,包括 transmute
现在已被弃用的事实。但好消息是,如果您愿意使用 formula.tools
,解决方案将非常简洁。如下图。
library(dplyr)
# reproducible play_data
set.seed(2020)
play_data <-
data.frame(
a = runif(20, 0.01, .5),
b = runif(20, 0.02, .5),
c = runif(20, 0.03, .5),
d = runif(20, 0.04, .5),
e = runif(20,1,5),
f = runif(20,10,50)
)
my_formula <- newvariable ~ a * b^c / d * log(e) - f
require(formula.tools)
mutate_by_formula <- function(df, equation){
df %>% transmute( !!lhs(equation) := !!rhs(equation) )
}
mutate_by_formula(play_data, my_formula)
#> newvariable
#> 1 -25.80405
#> 2 -20.48974
#> 3 -37.87361
#> 4 -46.52231
#> 5 -19.88420
#> 6 -16.49153
#> 7 -37.25498
#> 8 -41.02025
#> 9 -31.88338
#> 10 -42.17896
#> 11 -30.75905
#> 12 -10.42447
#> 13 -25.84538
#> 14 -46.08206
#> 15 -13.51940
#> 16 -25.30124
#> 17 -19.80536
#> 18 -26.42881
#> 19 -38.02190
#> 20 -30.51113
至于 OP 的原始示例和细节,它稍微复杂一些,因为必须对数据进行整形,但基本概念是相同的。唯一的转折是 dcast
和最后的 select
以删除计算中使用的变量。
library(dplyr)
library(reshape2)
library(formula.tools)
set.seed(100)
the_data <- data.frame(country = c(rep("USA", 9), rep("DEU", 9), rep("CHN", 9)),
year = c(2000, 2010, 2020),
variable = c(rep("GDP", 3), rep("Population", 3), rep("Consumption", 3)),
value = rnorm(27, 100, 100))
specific_function <- function(df, equation){
df %>%
filter(variable %in% all.vars(equation)) %>%
dcast(country + year ~ variable) %>%
mutate(!!lhs(equation) := !!rhs(equation)) %>%
select(-all.vars(equation)[2:length(all.vars(equation))])
}
specific_function(the_data, GDPpC ~ GDP / Population)
#> country year GDPpC
#> 1 CHN 2000 0.04885649
#> 2 CHN 2010 2.62313658
#> 3 CHN 2020 0.31685382
#> 4 DEU 2000 0.80180998
#> 5 DEU 2010 0.62642877
#> 6 DEU 2020 0.97587188
#> 7 USA 2000 0.26383912
#> 8 USA 2010 1.01303516
#> 9 USA 2020 0.69851501
由 reprex package (v0.3.0)
于 2020-05-04 创建