技巧 | 如何批量地将整型变量转换为因子变量

这是刚刚探索出来的一个小技巧,在这里记录一下!

对于个别变量的类型转换,例如从其他类型转化为因子变量,base包中的transform()函数或者dplyr包中的mutate()函数就可以快速完成:

library(tidyverse)
dta <- mtcars

# transform函数
dta %>%
  transform(cyl = factor(cyl),
            hp = factor(hp)) %>%
  as_tibble()

# mutate函数
dta %>%
  mutate(cyl = factor(cyl),
         hp = factor(hp)) %>%
  as_tibble() 

可以看出两个函数在管道操作符中的使用方式还是比较相似的,都是将所有需要转换的变量依次写入即可。

但是,当需要转换类型的变量比较多时,这种挨个写入变量名的方式就很不适用了。这里就需要使用dplyr包中的辅助函数across()了。

across()函数功能之一就是选择(select)指定变量名或符合约束条件的变量名,然后对这些变量进行函数运算,语法结构如下:

across(.cols = everything(), .fns = NULL, ..., .names = NULL)

上面.cols就是选择出的变量,.fns是应用于这些变量的函数。先列举几个常与它连用的辅助函数:

  • everyyhing():选择所有变量;

  • starts_with():选择变量名以特定字符开始的变量;

  • ends_with():选择变量名以特定字符结束的变量名。

上面的这些函数都来自于dplyr包,这里先不做详细介绍,后面会有推文总结dplyr中所有的辅助函数。另外关于dplyr包中“选择(select)”的含义前面推文已有介绍(dplyr | 数据导入和预处理的常用函数)。

为了批量地将一个数据框中所有的整型变量都转换为因子,第一步是要选择出所有整型变量。

首先想到判断整型变量的函数应该是is.integer(),但是在实操中发现,数据框的整型变量大多是以double(双精度)类型存在的,使用is.integer不会选择出任何变量,也就达不到目的;而由于double类型也包括小数,所以使用is.double会选择出多余的变量,同样达不到目的。对比结果如下:

dta %>%
  mutate(across(where(is.integer), factor)) %>%
  as_tibble()

dta %>%
  mutate(across(where(is.double), factor)) %>%
  as_tibble()
# 输出结果
> dta %>%
+   mutate(across(where(is.integer), factor)) %>%
+   as_tibble()
# A tibble: 32 x 11
     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
 1  21       6  160    110  3.9   2.62  16.5     0     1     4     4
 2  21       6  160    110  3.9   2.88  17.0     0     1     4     4
 3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1
 4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1
 5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2
 6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1
 7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4
 8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2
 9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2
10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4
# ... with 22 more rows

> dta %>%
+   mutate(across(where(is.double), factor)) %>%
+   as_tibble()
# A tibble: 32 x 11
   mpg   cyl   disp  hp    drat  wt    qsec  vs    am    gear  carb 
   <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct> <fct>
 1 21    6     160   110   3.9   2.62  16.46 0     1     4     4    
 2 21    6     160   110   3.9   2.875 17.02 0     1     4     4    
 3 22.8  4     108   93    3.85  2.32  18.61 1     1     4     1    
 4 21.4  6     258   110   3.08  3.215 19.44 1     0     3     1    
 5 18.7  8     360   175   3.15  3.44  17.02 0     0     3     2    
 6 18.1  6     225   105   2.76  3.46  20.22 1     0     3     1    
 7 14.3  8     360   245   3.21  3.57  15.84 0     0     3     4    
 8 24.4  4     146.7 62    3.69  3.19  20    1     0     4     2    
 9 22.8  4     140.8 95    3.92  3.15  22.9  1     0     4     2    
10 19.2  6     167.6 123   3.92  3.44  18.3  1     0     4     4    
# ... with 22 more rows

可以看出,使用is.integer没有任何变量被转化为factor类型,说明across()中没有被添加任何变量名;而使用is.double所有的变量都会被转化为factor类型。

由于上面两个函数都达不到目标,可以考虑从整数的特点出发,即整数除以1后的余数为0。R语言中的取余函数为%%,基于此,可以自定义一个“选择”函数:

function(x) all(x %% 1 == 0)

all()函数来自基础包base,如果函数内的判断条件成立会返回TRUE,否则返回FALSE。

把自定义函数应用到across()中:

dta %>%
  mutate(across(function(col) all(col %% 1==0), factor)) %>%
  as_tibble()
# 输出结果
> dta %>%
+   mutate(across(function(col) all(col %% 1==0), factor)) %>%
+   as_tibble()
# A tibble: 32 x 11
     mpg cyl    disp hp     drat    wt  qsec vs    am    gear  carb 
   <dbl> <fct> <dbl> <fct> <dbl> <dbl> <dbl> <fct> <fct> <fct> <fct>
 1  21   6      160  110    3.9   2.62  16.5 0     1     4     4    
 2  21   6      160  110    3.9   2.88  17.0 0     1     4     4    
 3  22.8 4      108  93     3.85  2.32  18.6 1     1     4     1    
 4  21.4 6      258  110    3.08  3.22  19.4 1     0     3     1    
 5  18.7 8      360  175    3.15  3.44  17.0 0     0     3     2    
 6  18.1 6      225  105    2.76  3.46  20.2 1     0     3     1    
 7  14.3 8      360  245    3.21  3.57  15.8 0     0     3     4    
 8  24.4 4      147. 62     3.69  3.19  20   1     0     4     2    
 9  22.8 4      141. 95     3.92  3.15  22.9 1     0     4     2    
10  19.2 6      168. 123    3.92  3.44  18.3 1     0     4     4    
# ... with 22 more rows

可以看出,数据框中所有的整型变量都已经被转化为factor类型了,而非整型变量依然是原本的double类型,也就达到了批量转换变量类型的目的了。如果有其他类似的需求,对自定义函数进行对应的修改就可以了。

 

 

  • 5
    点赞
  • 0
    评论
  • 13
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:1024 设计师:我叫白小胖 返回首页

打赏作者

R语言学堂

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值