#r #tidyeval
#r #tidyeval
Вопрос:
Я хочу изменить значение dataframe
/ tibble
column, определенное как переменная ( col_name
). Я !!col_name
безуспешно пытался.
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
col_name <- "b" # the column to select
df <- tibble(a = c(1,2,3), b = c(2,4,6))
df %>%
mutate(b = if_else((b == 6 amp; a == 3), 8, b)) # this works
#> # A tibble: 3 x 2
#> a b
#> <dbl> <dbl>
#> 1 1 2
#> 2 2 4
#> 3 3 8
# but this doesn't
df %>%
mutate(!!col_name := if_else((!!col_name == 6 amp; a == 3), 8, !!col_name))
#> Error: Problem with `mutate()` input `b`.
#> x `false` must be a double vector, not a character vector.
#> i Input `b` is `if_else(("b" == 6 amp; a == 3), 8, "b")`.
Created on 2020-10-13 by the reprex package (v0.3.0)
Ответ №1:
Использование базы:
df[ df[, col_name ] == 6 amp; df$a == 3, col_name ] <- 8
df
# a b
# 1 1 2
# 2 2 4
# 3 3 8
Примечание: Да, я знаю, что вопрос касается «аккуратности», это просто для иллюстрации того, почему для некоторых простых задач базовые решения так же хороши / лучше.
Ответ №2:
Для использования !!
в RHS вам необходимо сначала преобразовать col_name
в symbol.
library(dplyr)
df %>% mutate(!!col_name := if_else(!!sym(col_name) == 6 amp; a == 3,
8, !!sym(col_name)))
Другие альтернативы включают использование get
:
df %>% mutate(!!col_name := if_else(get(col_name) == 6 amp; a == 3,
8, get(col_name)))
Или без какого-либо использования NSE .data
:
df %>% mutate(!!col_name := if_else(.data[[col_name]] == 6 amp; a == 3,
8, .data[[col_name]]))
Комментарии:
1. Любой из трех методов предпочтительнее?
2. Лайонел (автор пакета
rlang
) недавно заявил, что использование.data
является предпочтительным методом сейчас. Об этом также следует упомянуть где-нибудь на веб-сайте rlang / tidyverse.