创建调用并在 tibble 列上循环

Creating a call and while looping over tibble columns

我写了一个函数来将 tibble 的字符变量转换为因子,进行一些操作,然后再次将因子转换回字符(如果它们首先是字符)。我想通过创建一个电话来做到这一点。

library(tidyverse)
library(stringr)
library(rlang)

N <- 100
d <- tibble(a = sample(LETTERS[1:4], N, replace = TRUE),
            b = sample(letters[20:23], N, replace = TRUE),
            x = round(rnorm(N, 100, 20), 1),
            y = as.numeric(sample(30:45, N, replace = TRUE)))

dplyr_xx <- function(d, ...) {
  call_vec <- map_chr(d, ~str_c("as.", class(.), sep = ""))
  d %>%
    mutate_if(is.character, as_factor) %>%
    # ... %>%
    imap_dfc(., ~ .x %>%
               exec(call_vec[.y])) # -> error
}
d %>%
  dplyr_xx(a, x, y)

如何修正上面的功能?

?exec 帮助页面,我们看到要调用的函数应作为第一个参数提供,然后是该函数的任何其他参数。

在你的例子中,call_vec[.y] 是函数,.x 是参数。当你写

.x %>% exec(call_vec[.y])

相当于

exec(.x, call_vec[.y])

参数顺序错误(函数现在是第二个参数,而不是第一个)。更改顺序可解决问题:

dplyr_xx <- function(d, ...) {
  call_vec <- map_chr(d, ~str_c("as.", class(.), sep = ""))
  d %>% mutate_if(is.character, as_factor) %>%
      ## ... %>%
      imap_dfc(., ~exec(call_vec[.y], .x))
}
d %>% dplyr_xx(a, x, y)
# # A tibble: 100 x 4
#    a     b         x     y
#    <chr> <chr> <dbl> <dbl>
#  1 A     t     150.     34
#  2 A     u     116.     32
#  3 C     w      81.2    30
# ...