R: условная оценка выражений, заданных в виде строк в качестве значений для dplyr mutate - PullRequest
0 голосов
/ 12 мая 2018

Я пытаюсь сделать dplyr :: mutate () с помощью case_when для выбора между различными формулами, которые собраны из частей, которые являются строками. Однако я явно не преобразую строку должным образом в выражение перед тем, как заключать их в кавычки, а затем удалять их. Я пробовал семь или восемь способов сделать это, но все безуспешно.

Причина сборки выражения из строк состоит в том, что у меня есть большое количество групп переменных, имена которых отличаются только суффиксом, например, чтобы различать переменные в номинальных или скорректированных на инфляцию долларах. Я использую case_when, потому что похожие переменные имеют разные имена, а иногда и разные структуры агрегации в разные годы.

Это очень упрощенный пример:

bus_inc <- function(tb, suffix) {
  bus1     <- quo(paste0("incbus", suffix, " + ",  "incfarm", suffix, collapse = ""))
  bus2     <- quo(paste0("incbus2", suffix, " + ",  "incfarm", suffix, collapse = ""))
  bus3     <- quo(paste0("incbus", suffix, " + ",  "incfarm2", suffix, collapse = ""))
  out      <- mutate(tb, bus = case_when((year < 1968) ~ UQ(bus1),
                                   ((year > 1967) & (year < 1976)) ~ UQ(bus2),
                                   (year > 1975) ~ UQ(bus3)))
  out
}

Данные:

incbus_99     <-   1:56
incfarm_99   <-  57:112
incbus2_99   <-  incbus_99 + 0.5
incfarm2_99 <-  incfarm_99 * 10
year <- 1962:2017
test_tb <- tibble(year, incbus_99, incfarm_99, incbus2_99, incfarm2_99)

my_test <- bus_inc(tb  = test_tb, suffix = "_99")
my_test

Значение bus должно быть 58 в 1962 году и 70,5 в 1968 году.

Я нашел несколько мест, которые предлагают синтаксический анализ (text = "my_string") в качестве способа преобразования строки в выражение, например, в этом раннем примере (2002) от Мартина Мачлера. Но я также нашел множество мест, где говорят, что никогда не делают этого, например, Fortune 106 и этот недавний пример от Мартина Мачлера. Я принимаю это решительное отрицание грозным доктором Мехлером решения, которое он бесценно предложил, как убедительное доказательство того, что это не очень хорошая идея, но я не понимаю его предлагаемых альтернатив, поскольку они, похоже, оцениваются как строки.

1 Ответ

0 голосов
/ 12 мая 2018

может использовать комбинацию sym() и expr() (вам также нужно использовать as.numeric, потому что несовместимые типы приведут к ошибке в case_when) ...

bus_inc <- function(tb, suffix) {
  bus1 <- expr(!!sym(paste0('incbus', suffix)) + !!sym(paste0('incfarm', suffix)))
  bus2 <- expr(!!sym(paste0('incbus2', suffix)) + !!sym(paste0('incfarm', suffix)))
  bus3 <- expr(!!sym(paste0('incbus', suffix)) + !!sym(paste0('incfarm2', suffix)))
  mutate(tb, bus = case_when(year < 1968 ~ as.numeric(!!bus1),
                             year > 1967 & year < 1976 ~ as.numeric(!!bus2),
                             year > 1975 ~ as.numeric(!!bus3)))
}

library(dplyr)

incbus_99     <-   1:56
incfarm_99   <-  57:112
incbus2_99   <-  incbus_99 + 0.5
incfarm2_99 <-  incfarm_99 * 10
year <- 1962:2017
test_tb <- tibble(year, incbus_99, incfarm_99, incbus2_99, incfarm2_99)

bus_inc(tb  = test_tb, suffix = "_99")

# # A tibble: 56 x 6
#     year incbus_99 incfarm_99 incbus2_99 incfarm2_99   bus
#    <int>     <int>      <int>      <dbl>       <dbl> <dbl>
#  1  1962         1         57        1.5         570  58  
#  2  1963         2         58        2.5         580  60  
#  3  1964         3         59        3.5         590  62  
#  4  1965         4         60        4.5         600  64  
#  5  1966         5         61        5.5         610  66  
#  6  1967         6         62        6.5         620  68  
#  7  1968         7         63        7.5         630  70.5
#  8  1969         8         64        8.5         640  72.5
#  9  1970         9         65        9.5         650  74.5
# 10  1971        10         66       10.5         660  76.5
# # ... with 46 more rows
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...