r语言 - 使用 across() 选择变量的复杂'if'条件



假设我想将列转换为数值,如果它们包含0、1、2、NA并且具有3个或更少的唯一值。

之前我用完成了这项工作

outcome_data<- outcome_data %>% dplyr::mutate_if(~any(c(0, 1, 2, NA) %in% .x) & length(unique(as.numeric(.x))) <= 3, as.numeric)

但目前还不清楚如何将.x作为across()的第一个参数来创建复杂的if条件。以下提示错误:

未找到对象'.x'

outcome_data %>% mutate(across(any(c(0, 1, 2, NA) %in% .x) & length(unique(.x)) < 3), as.numeric))

为了用有效的下标向量对列进行子集设置,我们需要一个数字或字符向量,这里有一种使用whichsapply的方法

#devtools::install_github("tidyverse/dplyr")
library(dplyr, warn.conflicts = FALSE)
mtcars %>% 
# which(sapply(., function(x) any(c(0, 1, 2, NA) %in% x) & n_distinct(x) < 3))
mutate(across(.cols = which(sapply(., function(x) n_distinct(x)<3)), as.character)) %>% 
str()

来自?across

cols,.cols:tree选择要转换的列。由于across((用于summary((和mutate((等函数中,因此不能在对变量分组时进行选择或计算。

我感谢大家对此的回应。我同意,在我看来,across()并不能让这类事情变得容易,需要额外的步骤。

以下是我解决问题的方法:

dummy_vars<- outcome_data %>% purrr::keep(~all(c("0", "1") %in% .x) & length(unique(.x)) <= 3) %>% names()
outcome_data<- outcome_data %>% dplyr::mutate(across(all_of(dummy_vars), as.numeric))

dplyrGithub上有一系列关于这个主题的问题,所以他们现在实现了一个接受谓词的函数where()。与across一样,它目前可通过remotes::install_github('tidyverse/dplyr')使用。

按照A.Suliman的例子,我们现在可以使用:

library(dplyr)
mtcars %>%
mutate(across(.cols = where(~any(c(0, 1, 2, NA) %in% .x) & length(unique(as.numeric(.x))) <= 3), 
as.character)) %>%
str()
#> 'data.frame':    32 obs. of  11 variables:
#>  $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
#>  $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
#>  $ disp: num  160 160 108 258 360 ...
#>  $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
#>  $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
#>  $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
#>  $ qsec: num  16.5 17 18.6 19.4 17 ...
#>  $ vs  : chr  "0" "0" "1" "1" ...
#>  $ am  : chr  "1" "1" "1" "0" ...
#>  $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
#>  $ carb: num  4 4 1 1 2 1 4 2 2 4 ...

最新更新