2

我正在尝试编写一个ifelse()我想传递给dplyr::mutate(across()). 该函数应将 中指定的列中的 NA 值替换across()为名称相似的列中的值。

例如,在以下虚构数据中,我想用 替换缺失x_var1y_var1缺失:x_var2y_var2

x <- tribble(~x_var1, ~x_var2, ~y_var1, ~y_var2,
             5, 2, 0, 0,
             NA, 10, 8, 0,
             3, NA, 0, 5,
             NA, NA, 7, 9)   

我尝试构建以下函数:

ifelse_spec <- function(var) {
  new_var = paste("y_", str_remove(cur_column(), "x_"), sep = "")
 
  # print(new_var) # just to check new_var is correct 

  ifelse(is.na(var), !!sym(new_var) , var)  # how to call new_var?
}

x %>%
  mutate(across(c(x_var1, x_var2),
                ~ ifelse_spec(.)))

但它似乎不起作用。

但是,如果我直接运行这个单变量案例ifelse,我会得到预期的结果。

x %>% 
  mutate(across(c(x_var1),
                ~ifelse(is.na(.), !!sym("y_var1"), .)))

如何构建允许我调用数据变量的自定义 ifelse 语句?

编辑:我得到以下适用于多变量情况,但仍在使用ifelse而不是不同的功能。

x %>% 
  mutate(across(c(x_var1, x_var2),
                ~ifelse(is.na(.), eval(sym(paste("y_", str_remove(cur_column(), "x_"), sep = ""))), . )))
4

1 回答 1

1

coalesce()是针对这个问题设计的(填充其他列中的缺失值)。您可以通过使用它而不是简化单变量案例ifelse

library(dplyr, warn.conflicts = FALSE)
library(stringr)
library(purrr)

x <- tribble(~x_var1, ~x_var2, ~y_var1, ~y_var2,
             5, 2, 0, 0,
             NA, 10, 8, 0,
             3, NA, 0, 5,
             NA, NA, 7, 9)

x %>% 
  mutate(x_var1 = coalesce(x_var1, y_var1))
#> # A tibble: 4 x 4
#>   x_var1 x_var2 y_var1 y_var2
#>    <dbl>  <dbl>  <dbl>  <dbl>
#> 1      5      2      0      0
#> 2      8     10      8      0
#> 3      3     NA      0      5
#> 4      7     NA      7      9

然后,您可以使用它select()来概括它以合并名称相似的列:

x %>% 
  mutate(x_var1 = do.call(coalesce, select(., ends_with("var1"))))
#> # A tibble: 4 x 4
#>   x_var1 x_var2 y_var1 y_var2
#>    <dbl>  <dbl>  <dbl>  <dbl>
#> 1      5      2      0      0
#> 2      8     10      8      0
#> 3      3     NA      0      5
#> 4      7     NA      7      9

最后,使用map_dfc将此函数应用于每一列,使用模式匹配来提取它所属的“列组”:

x %>% 
  colnames() %>% 
  str_extract("var[0-9]") %>% 
  set_names(colnames(x)) %>% 
  map_dfc(~do.call(coalesce, select(x, ends_with(.))))
#> # A tibble: 4 x 4
#>   x_var1 x_var2 y_var1 y_var2
#>    <dbl>  <dbl>  <dbl>  <dbl>
#> 1      5      2      5      2
#> 2      8     10      8     10
#> 3      3      5      3      5
#> 4      7      9      7      9

您将需要调整str_extract()ends_with()适应真实数据中的列名,但我认为这应该推广到任何合理的命名方案。如果将自定义函数应用于您的真实数据而不是 很重要coalesce(),那么也应该可以重写map_dfc()以使用它。

于 2021-02-18T10:52:48.163 回答