R语言使用sapply按条件修改数据框因子水平失效问题排查
问题原因
你代码失效是两个核心问题导致的:
apply()处理数据框时会先把所有输入强制转换为原子矩阵,因子列的属性会被直接抹除转成普通字符串,你函数里的is.factor()判断永远不会触发,清洗逻辑完全没执行,最后再转回因子时自然保留了所有重复的原始值。- 你写的
match_levels函数本身逻辑有漏洞:对levels赋值时错误遍历了整列值而非水平向量,正则没有覆盖空格变体,大小写统一操作没有真正落地到水平上,没法合并大小写不同的同义值。
修正代码
首先重写可靠的清洗函数,再用lapply()(而非apply())按列遍历,保留每列的原始属性:
# 因子水平统一清洗函数 match_levels <- function(col) { # 非因子列直接原样返回 if (!is.factor(col)) return(col) # 1. 所有因子水平统一转小写,消除大小写差异 clean_lv <- tolower(levels(col)) # 2. 移除所有"数字+任意空格+冒号+任意空格"格式的冗余前缀 clean_lv <- sub("\\d+\\s*:\\s*", "", clean_lv) # 3. 可选:统一缩写差异,把6 mons替换为全称6 months clean_lv <- sub("no intercourse in last 6 mons", "no intercourse in last 6 months", clean_lv) # 赋值回水平,R会自动合并完全一致的重复水平 levels(col) <- clean_lv return(col) } # 读取数据(R4.0+版本注意加stringsAsFactors参数保证分类列读为因子) dat <- read.csv("你的数据文件本地路径.csv", stringsAsFactors = TRUE) # 对所有列应用清洗函数 dat_clean <- as.data.frame(lapply(dat, match_levels))
效果验证
清洗后再查看ABLECLM列的水平,所有同义重复项会被合并:
levels(dat_clean$ABLECLM)
输出为统一后的6个水平:
[1] "(1) always" "(2) almost always" [3] "(3) sometimes" "(4) almost never" [5] "(5) never" "(6) no intercourse in last 6 months"
注意:不要用
apply()处理带不同类型列的数据框,它的矩阵转换逻辑会丢失列属性,按列操作数据框优先选lapply()。
内容的提问来源于stack exchange,提问作者Casey Jayne
相关产品推荐
相关产品推荐

