Мутировать столбцы данных в зависимости от массива символов? - PullRequest
0 голосов
/ 02 ноября 2018

Как я могу изменить столбцы данных на основе символьного массива выражений? Например,

У меня есть:

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 решения идеальны, но не обязательны.

1 Ответ

0 голосов
/ 04 ноября 2018

Сплайсинг без кавычек (rlang's !!!) хорошо подходит для этой задачи.

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)
  )

Что эквивалентно сначала захвату цитируемых выражений, а затем объединению их в ... из 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)

Конечно, я думаю, что в будущем вам будет легче читать первую версию (без кавычек и сплайсинга), но если вы хотите уменьшить дублирование кода, я мог бы увидеть аргумент для второго примера (quosures1). По этой причине я стараюсь не хранить выражения в виде строк.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...