R语言中lapply()结合is.numeric()处理数据框的异常行为问询
R语言中lapply结合ifelse与is.numeric的异常行为解析
先看你给出的代码场景:
创建测试数据框:
ddd <- data.frame(a=c(2,3,4), b=c(10,20,30)) ddd # a b # 1 2 10 # 2 3 20 # 3 4 30
直接用lapply对列做乘法,结果符合预期:
lapply(ddd, function(x) x*100 ) # $a # [1] 200 300 400 # # $b # [1] 1000 2000 3000
但用ifelse结合is.numeric(x)时,只返回了第一行结果:
lapply(ddd, function(x) ifelse( is.numeric(x), x*100, x ) ) # $a # [1] 200 # # $b # [1] 1000
而结合is.na(x)后又恢复正常:
lapply(ddd, function(x) ifelse( is.numeric(x) & !is.na(x), x*100, x ) ) # $a # [1] 200 300 400 # # $b # [1] 1000 2000 3000
问题原因
核心在于ifelse()的工作逻辑和is.numeric()的返回值特性:
is.numeric(x)是对整个向量的类型做判断,返回的是一个长度为1的逻辑值(这里两列都是数值型,所以返回TRUE)。ifelse(test, yes, no)要求测试条件test的长度必须和yes/no的长度匹配。如果test是长度1的逻辑值,它只会提取yes或no的第一个元素返回,所以最终只得到了x*100的第一个值。
而当你加上!is.na(x)后:
is.na(x)是对向量的每个元素做检查,返回和x长度相同的逻辑向量(这里是c(FALSE, FALSE, FALSE))。- R会自动把长度为1的
is.numeric(x)循环补齐成和!is.na(x)一样的长度,得到c(TRUE, TRUE, TRUE),此时test的长度和x*100的长度一致,ifelse就会返回所有元素的计算结果。
更合适的写法
既然你是判断整列的类型,而非单个元素,直接用普通的if语句更直观,也不会出问题:
lapply(ddd, function(x) { if(is.numeric(x)) x*100 else x })
内容的提问来源于stack exchange,提问作者samsamara
相关产品推荐
相关产品推荐

