如何基于表达式的字符数组来更改数据框的列?例如,
我有:
library(tidyverse)
dat <- data_frame(id = 0:4,
brand = c(NA, 'coke', 'pepsi', 'other', 'pepsi'),
price = as.character(c(NA, 1, 1.10, 1.25, .99)))
model_feature_definitions_tmp <-
data_frame(feature_id = 0:3,
feature_name = c("intercept", "brand_coke", "brand_pepsi", "price"),
feature_definition = c("as.numeric(id != 0)", "as.numeric(brand == 'coke')",
"as.numeric(brand == 'pepsi')", "as.numeric(price)"))
我想要:
# # A tibble: 5 x 4
# intercept brand_coke brand_pepsi price
# <dbl> <dbl> <dbl> <dbl>
# 1 0 NA NA NA
# 2 1 1 0 1.00
# 3 1 0 1 1.10
# 4 1 0 0 1.25
# 5 1 0 1 0.99
以下作品:
library(tidyverse)
res_list <- list()
n <- nrow(model_feature_definitions_tmp)
for (i in 1:n) {
mfd_i <- slice(model_feature_definitions_tmp, i)
dat %>%
transmute(eval(parse(text=mfd_i$feature_definition))) ->
res_list[[i]]
}
res_list %>%
bind_cols() %>%
setNames(model_feature_definitions_tmp$feature_name) ->
model_feature_space
但是我怀疑这是最好的方法。我想有一种更好的方法,它不涉及for循环或*apply
函数。也许可以在这里使用purrr
包?
tidyverse
解决方案是理想的,但不是必需的。
答案 0 :(得分:1)
取消引号拼接(rlang的!!!
)可以很好地完成此任务。
library(tidyverse)
dat <-
data_frame(
id = 0:4,
brand = c(NA, 'coke', 'pepsi', 'other', 'pepsi'),
price = as.character(c(NA, 1, 1.10, 1.25, .99))
)
defs <-
data_frame(
feature_name = c("intercept", "brand_coke", "brand_pepsi", "price"),
feature_definition =
c("as.numeric(id != 0)", "as.numeric(brand == 'coke')",
"as.numeric(brand == 'pepsi')", "as.numeric(price)")
)
本质上,您正在尝试执行以下操作(我认为吗?):
dat %>%
transmute(
intercept = as.numeric(id != 0),
brand_coke = as.numeric(brand == 'coke'),
brand_pepsi = as.numeric(brand == 'pepsi'),
price = as.numeric(price)
)
这等同于首先捕获带引号的表达式,然后将它们拼接到...
的{{1}}中:
dplyr::transmute
但是,您将表达式存储为字符串,因此必须将它们解析为可以加引号的表达式。在这里,我在字符串上进行映射以生成一个表达式列表,然后将它们拼接到quosures1 <-
quos(
intercept = as.numeric(id != 0),
brand_coke = as.numeric(brand == 'coke'),
brand_pepsi = as.numeric(brand == 'pepsi'),
price = as.numeric(price)
)
transmute(dat, !!! quosures1)
中,以构成一个数量表。我为列表中的元素命名,以便它们在quos
中用作LHS名称:
transmute
当然,我认为第一个版本(不带引号和剪接)对于以后的读者来说会更容易阅读,但是如果您想减少代码重复,我可以看到第二个示例的参数(quosures2 <-
quos(!!! map(defs$feature_definition, rlang::parse_expr)) %>%
set_names(defs$feature_name)
transmute(dat, !!! quosures2)
)。因此,我倾向于避免将表达式存储为字符串。