为何R语言dplyr::mutate中含is.na的if条件语句报错?
问题说明
先给出测试用的最小数据集:
test <- data.frame( RowNum = c(0, 1, 2, 3, 4, NA, NA) )
下面两段代码都能正常运行:
可运行代码1
test <- test %>% dplyr::mutate(rotCertCount = ( (is.na(RowNum)) ))
可运行代码2
test <- test %>% dplyr::mutate(rotCertCount = ( if (TRUE) 0 else 1 ))
但运行下面这段代码时会报错:
报错代码
test <- test %>% dplyr::mutate(rotCertCount = ( if (is.na(RowNum)) 0 else 1 ))
报错信息如下:
Error in
dplyr::mutate():
ℹ In argument:rotCertCount = (if (is.na(RowNum)) 0 else 1).
Caused by error inif (is.na(RowNum)) ...:
! the condition has length > 1
Runrlang::last_trace()to see where the error occurred.
报错原因
- 基础R里的
if是标量判断语句,它只能接受单个逻辑值(要么TRUE要么FALSE),没法处理长度大于1的逻辑向量。 - 在
mutate中调用is.na(RowNum),会返回一个和数据集行数一致的逻辑向量(这里是长度为7的向量),把这个向量直接传给if,就会触发"条件长度大于1"的错误。 - 再看能运行的代码:
- 代码1直接用
is.na(RowNum),dplyr会自动把逻辑值转成数值(TRUE对应1,FALSE对应0),所以能正常生成新列。 - 代码2里的
if (TRUE)是单个标量条件,返回固定值0,dplyr会把这个值自动填充到所有行,因此也能运行。
- 代码1直接用
解决办法
要在mutate里实现逐行的条件判断,得用向量化的条件函数:
- 用dplyr自带的
if_else()(专门适配tidyverse的向量化判断):
test <- test %>% dplyr::mutate(rotCertCount = if_else(is.na(RowNum), 0, 1))
- 或者用基础R的
ifelse()(注意是全小写的,和标量if不是同一个东西):
test <- test %>% dplyr::mutate(rotCertCount = ifelse(is.na(RowNum), 0, 1))
内容的提问来源于stack exchange,提问作者monkey
相关产品推荐
相关产品推荐

