如何在dplyr的case_when中使用函数与多参数?
解决dplyr::case_when中混合字符与数值输出的问题
问题背景
用嵌套ifelse可以实现多条件逻辑,同时返回字符、计算值和缺失值:
#### Load Library #### library(tidyverse) #### Run Multiple Ifelse Statements #### iris %>% mutate(New.Sepal.Width = ifelse(Sepal.Width > 3.5, "Large", ifelse(Sepal.Width < 3, sqrt(Sepal.Width), NA)))
但转用case_when时遇到两个问题:
- 将
sqrt(Sepal.Width)用引号包裹,输出的是字符串而非计算后的平方根值 - 直接调用
sqrt(Sepal.Width)会触发类型不匹配的报错
错误原因
case_when要求所有分支的返回值类型必须一致:
- 你写的
"Large"是字符型,sqrt(Sepal.Width)是数值型,"NA"是字符串型,三种类型冲突导致报错 - 另外,
"NA"是字符串,不是真正的缺失值,应该用无引号的NA
解决方案
统一所有分支的返回值类型,这里有两种常用方式:
方式1:将数值结果转为字符型,统一返回字符/缺失值
把平方根计算结果转成字符,同时用NA_character_指定字符型缺失值(和"Large"类型匹配):
iris %>% mutate(New.Sepal.Width = case_when( Sepal.Width > 3.5 ~ "Large", Sepal.Width < 3 ~ as.character(sqrt(Sepal.Width)), TRUE ~ NA_character_ # 用TRUE匹配剩余所有情况,替代冗余的条件判断 ))
方式2:保持数值型,将"Large"转为数值型缺失值(适合不需要字符结果的场景)
如果不需要"Large"字符,可将其替换为数值型缺失值,统一返回数值/缺失值:
iris %>% mutate(New.Sepal.Width = case_when( Sepal.Width > 3.5 ~ NA_real_, # 数值型缺失值 Sepal.Width < 3 ~ sqrt(Sepal.Width), TRUE ~ NA_real_ ))
关键要点
- 不要用引号包裹函数调用,直接写
sqrt(Sepal.Width)才会执行计算,而非输出字符串 - 用
TRUE ~ ...匹配所有未被前面条件覆盖的情况,无需写冗余的Sepal.Width > 3 & Sepal.Width < 3.5 - 必须保证所有分支返回值类型一致:
- 字符型分支对应
NA_character_(字符型缺失值) - 数值型分支对应
NA_real_(数值型缺失值) - 逻辑型分支对应
NA
- 字符型分支对应
内容的提问来源于stack exchange,提问作者Shawn Hemelstrand
相关产品推荐
相关产品推荐

