R语言apply函数整数列逻辑判断恒假、字符列正常原因问询
问题产生的核心原因
这个坑完全是apply()处理数据框的默认机制导致的:
apply()按行(MARGIN=1)处理数据框时,会先把输入的整个数据框强制转换成原子矩阵,而原子矩阵要求所有元素必须是同一种数据类型,转换时会按照「逻辑型 < 整型 < 数值型 < 字符型」的优先级做全局类型提升,过程中会丢失列的原始属性、甚至隐式转换值的内容。- 你遇到判断全失效的直接原因是:当a列为整型时,只要你的原始数据框里混有因子、带标签的调研数据类型(比如haven包读入的带标签整数)、或者其他非数值/整型列,a列的值会在转矩阵的过程中被隐式转换:最常见的情况是数值类列被意外转成因子后,apply会把因子转成从1开始的水平编码,而不是你看到的0-5的表面值,这时候你写的
x["a"] == 0到x["a"] ==4的判断全部不成立,自然全走else分支返回"f"。 - 你用
as.character()把a列转成字符型后,apply转矩阵时会把整个矩阵统一提升为字符型,这时候x["a"]取到的就是你肉眼看到的"0""1"…"5"的文本值,==比较时R会自动做类型兼容,判断就可以正常命中。
代码本身的不合理之处
你写的自定义函数里的x["b"] = "a"这类操作完全是无效代码:x是apply逐行处理时生成的临时向量,和原数据框没有任何绑定关系,你对x的赋值既不会修改原数据,也没必要——R函数默认返回最后一个执行的表达式结果,你直接返回要赋给b列的值即可,不需要给临时向量加b列元素。
另外这种固定值匹配的场景完全没必要用apply逐行循环,不仅容易踩类型转换的坑,执行效率也远低于向量化操作。
更稳妥的实现方案
优先用查表法,代码简洁、效率最高,不会出现类型转换问题:
# 构建值和目标输出的映射关系 value_map <- c("0" = "a", "1" = "b", "2" = "c", "3" = "d", "4" = "e", "5" = "f") # 直接按a列值匹配,全程不涉及隐式类型转换 df$b <- value_map[as.character(df$a)]
如果要保留条件判断的写法,直接用向量化判断函数,不要走apply转矩阵的逻辑:
# 基础R嵌套ifelse实现 df$b <- with(df, ifelse(a == 0, "a", ifelse(a == 1, "b", ifelse(a == 2, "c", ifelse(a == 3, "d", ifelse(a == 4, "e", "f"))))))
内容的提问来源于stack exchange,提问作者grapeporcupine
相关产品推荐
相关产品推荐

