根据条件(唯一值的长度)跨多列进行变异

3

我正在尝试在 mutate() + across() 中创建一个函数,将具有五个或更少唯一值(或任意数量)的变量转换为因子,以便稍后使用这些因子进行分组。我认为函数的逻辑是正确的,但我得到了一些不正确的维度错误(西班牙语错误)。为简单起见,我正在使用 mtcars 数据库。

mtcars %>%
    mutate(across(1:ncol(.), 
        function(x) {
                if_else(length(unique(x[,i]))<=5, 
            as.factor(x), 
          x)}
    ))

Error: Problem with `mutate()` input `..1`.
i `..1 = across(...)`.
x número incorreto de dimensiones
Run `rlang::last_error()` to see where the error occurred.

非常感谢您的帮助和建议。

2个回答

3

在这里,我们需要使用if/else,因为ifelse/if_else要求所有参数长度相等。而length(unique()表达式返回长度为1的逻辑值,可能会导致条件失败。此外,使用dplyr,我们可以使用select-helpers,即everything()选择所有列。

library(dplyr)
out <- mtcars %>%
    mutate(across(everything(), 
        function(x) {
                if(length(unique(x))<=5) 
            as.factor(x) else  
          x}
    ))

-输出

> str(out)
'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 : Factor w/ 3 levels "4","6","8": 2 2 1 2 3 2 3 1 1 2 ...
 $ 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  : Factor w/ 2 levels "0","1": 1 1 2 2 1 2 1 2 2 2 ...
 $ am  : Factor w/ 2 levels "0","1": 2 2 2 1 1 1 1 1 1 1 ...
 $ gear: Factor w/ 3 levels "3","4","5": 2 2 2 1 1 1 1 2 2 2 ...
 $ carb: num  4 4 1 1 2 1 4 2 2 4 ...

此外,lambda函数可以用~简洁表示,并利用n_distinct
mtcars %>% 
   mutate(across(everything(), 
        ~ if(n_distinct(.x) <=5) as.factor(.x) else .x))

1
我完全忘记了everything(),而且我也看到x[,i]索引是不必要的。非常感谢! - Alejandro Carrera
@AlejandroCarrera 是的,这是一个for each循环。 - akrun
1
我很感激你以我的代码为起点并进行必要的改进。此外,你还提出了额外且有用的方法。非常感谢。 - Alejandro Carrera

3
另一种方法是在 across 内部使用 where 中的谓词函数。
我们可以定义一个自定义函数:
library(dplyr)

few_unique_vals <- function(x) {
  length(unique(x))<=5
}

mtcars %>% 
  mutate(across(where(few_unique_vals), as.factor)) %>%
  glimpse # for better printing

#> Rows: 32
#> Columns: 11
#> $ mpg  <dbl> 21.0, 21.0, 22.8, 21.4, 18.7, 18.1, 14.3, 24.4, 22.8, 19.2, 17.8,~
#> $ cyl  <fct> 6, 6, 4, 6, 8, 6, 8, 4, 4, 6, 6, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 8,~
#> $ disp <dbl> 160.0, 160.0, 108.0, 258.0, 360.0, 225.0, 360.0, 146.7, 140.8, 16~
#> $ hp   <dbl> 110, 110, 93, 110, 175, 105, 245, 62, 95, 123, 123, 180, 180, 180~
#> $ drat <dbl> 3.90, 3.90, 3.85, 3.08, 3.15, 2.76, 3.21, 3.69, 3.92, 3.92, 3.92,~
#> $ wt   <dbl> 2.620, 2.875, 2.320, 3.215, 3.440, 3.460, 3.570, 3.190, 3.150, 3.~
#> $ qsec <dbl> 16.46, 17.02, 18.61, 19.44, 17.02, 20.22, 15.84, 20.00, 22.90, 18~
#> $ vs   <fct> 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,~
#> $ am   <fct> 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,~
#> $ gear <fct> 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 3,~
#> $ carb <dbl> 4, 4, 1, 1, 2, 1, 4, 2, 2, 4, 4, 3, 3, 3, 4, 4, 4, 1, 2, 1, 1, 2,~

或者我们可以使用一个匿名的 purrr 风格的函数:

mtcars %>% 
  mutate(across(where(~ length(unique(.x))<=5),
                as.factor)) %>%
  glimpse # for better printing

#> Rows: 32
#> Columns: 11
#> $ mpg  <dbl> 21.0, 21.0, 22.8, 21.4, 18.7, 18.1, 14.3, 24.4, 22.8, 19.2, 17.8,~
#> $ cyl  <fct> 6, 6, 4, 6, 8, 6, 8, 4, 4, 6, 6, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 8,~
#> $ disp <dbl> 160.0, 160.0, 108.0, 258.0, 360.0, 225.0, 360.0, 146.7, 140.8, 16~
#> $ hp   <dbl> 110, 110, 93, 110, 175, 105, 245, 62, 95, 123, 123, 180, 180, 180~
#> $ drat <dbl> 3.90, 3.90, 3.85, 3.08, 3.15, 2.76, 3.21, 3.69, 3.92, 3.92, 3.92,~
#> $ wt   <dbl> 2.620, 2.875, 2.320, 3.215, 3.440, 3.460, 3.570, 3.190, 3.150, 3.~
#> $ qsec <dbl> 16.46, 17.02, 18.61, 19.44, 17.02, 20.22, 15.84, 20.00, 22.90, 18~
#> $ vs   <fct> 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,~
#> $ am   <fct> 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,~
#> $ gear <fct> 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 3,~
#> $ carb <dbl> 4, 4, 1, 1, 2, 1, 4, 2, 2, 4, 4, 3, 3, 3, 4, 4, 4, 1, 2, 1, 1, 2,~

本文内容由 reprex软件包(版本2.0.1)于2022-03-15创建。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接