【问题标题】:`r`/`rlang`/`dplyr`: How to render `sym` resilient to `NULL`?`r`/`rlang`/`dplyr`:如何使 `sym` 对 `NULL` 有弹性?
【发布时间】:2021-03-30 17:45:37
【问题描述】:

根据@akrun 的见解编辑:

这行得通:

require("magrittr")
requireNamespace("dplyr")

df <- data.frame(a = 1:5)

b_column <- c_column <- "a"
df %>% dplyr::mutate(
    b = !!dplyr::sym(b_column),
    c = !!dplyr::sym(c_column))

但是当*_columns 中的任何一个是NULL 时,它不会:

c_column <- NULL
df %>% dplyr::mutate(
    b = !!dplyr::sym(b_column),
    c = !!dplyr::sym(c_column))

产生的错误是:

Error: Only strings can be converted to symbols
Run `rlang::last_error()` to see where the error occurred.

我将如何调用任何 ensymboled *_column 变量以适应 NULL

【问题讨论】:

  • NULL 不是字符串,列名不能是NULL
  • 好吧,但是在匹配参数时,潜在的字符串默认为 NULL 是很常见的......
  • 你需要if(!is.null(c)) df %&gt;% dplyr::mutate(b = !!dplyr::sym(c))

标签: r dplyr rlang


【解决方案1】:

如果我们需要检查 NULL 大小写,请使用 if 条件

df1 <- if(!is.null(c)) {
       df %>%
          dplyr::mutate(b = !!dplyr::sym(c))
         } else df

对于多列,一个选项是map

library(purrr)
b_column <- c_column <- "a"
map2_dfc(list(b_column, c_column), c("b", "c"), ~ 
    if(!is.null(.x)) df %>% 
               transmute(!! .y := !! sym(.x))) %>% 
  bind_cols(df, .)

-输出

#  a b c
#1 1 1 1
#2 2 2 2
#3 3 3 3
#4 4 4 4
#5 5 5 5

如果其中之一是NULL

c_column <- NULL
map2_dfc(list(b_column, c_column), c("b", "c"), ~  
         if(!is.null(.x)) df %>%
                     transmute(!! .y := !! sym(.x))) %>%
  bind_cols(df, .)
#  a b
#1 1 1
#2 2 2
#3 3 3
#4 4 4
#5 5 5

另一个选项是mutateacross,但请确保我们只需要rename 不为NULL 的列

nm1 <- c("b", "c")
i1 <-  !map_lgl(list(b_column, c_column), is.null)
nm2 <- nm1[i1]
df %>% 
   mutate(across(all_of(c(b_column, c_column)), ~ .)) %>% 
   rename_at(vars(everything()), ~ nm2) %>% 
   bind_cols(df, .)

【讨论】:

  • @balin 我假设您想在c 的值为NULL 时返回原始数据集
  • 这确实接近用例。但是请参阅我上面的编辑...
  • @balin 你能检查更新的解决方案吗
猜你喜欢
  • 2018-08-18
  • 1970-01-01
  • 1970-01-01
  • 2019-02-04
  • 2019-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多