基于tidyverse实现:依用户参数是否为空的条件列类型转换方法
问题
需要用tidyverse工具实现数据类型的条件转换:以mtcars数据集为例,将cyl列转换为factor类型,其levels和labels参数需根据是否传入bin.order对象(或该对象是否为NULL)来确定。
当前尝试的代码如下:
mtcars %>% mutate(cyl = ifelse(is.null(bin.order), factor(x = cyl, levels = sort(unique(cyl)), labels = sort(unique(cyl))), factor(x = cyl, levels = bin.order, labels = bin.order)))
期望实现效果:
- 当
bin.order为NULL时:
mtcars %>% mutate(cyl = factor(x = cyl, levels = sort(unique(cyl)), labels = sort(unique(cyl))))
- 当
bin.order不为NULL时(例如bin.order = c(4, 6, 8)):
bin.order = c(4, 6, 8) mtcars %>% mutate(cyl = factor(x = cyl, levels = bin.order, labels = bin.order))
解决方案
可以利用tidyverse生态中rlang包提供的%||%运算符(该运算符会在左侧对象为NULL时返回右侧值,否则返回左侧值),大幅简化代码,避免重复调用factor函数:
library(tidyverse) # 情况1:bin.order为NULL bin.order <- NULL mtcars %>% mutate(cyl = factor( cyl, levels = bin.order %||% sort(unique(cyl)), labels = bin.order %||% sort(unique(cyl)) )) # 情况2:bin.order不为NULL bin.order <- c(4, 6, 8) mtcars %>% mutate(cyl = factor( cyl, levels = bin.order %||% sort(unique(cyl)), labels = bin.order %||% sort(unique(cyl)) ))
如果不想依赖rlang的运算符,也可以用base R的if标量判断提前定义参数,同样能简化代码:
# 先定义levels和labels的取值 levels_labs <- if (is.null(bin.order)) sort(unique(mtcars$cyl)) else bin.order mtcars %>% mutate(cyl = factor(cyl, levels = levels_labs, labels = levels_labs))
这两种方式都能实现需求,且代码更简洁易读,符合tidyverse的风格。
内容的提问来源于stack exchange,提问作者Jst2Wond3r
相关产品推荐
相关产品推荐

