如何在data.table中按条件批量替换无效值(规避循环)
嘿,我明白你遇到的问题了——想用data.table批量替换匹配无效值的元素,不想用循环,但直接用%in%的写法没生效对吧?
首先得说清楚,data.table的索引逻辑和普通data.frame不太一样,你原来的DT[DT %in% invalid_values] <- -99写法之所以不工作,是因为data.table里DT[i, j]的i参数是用来筛选行的,而你这里生成的是一个和表格同维度的逻辑矩阵,data.table没法正确解析这个来定位要替换的元素。
给你几个不用循环的高效解决方案:
方案1:用.SD + lapply(兼容所有data.table版本)
如果想生成新表,用这个:
DT_cleaned <- DT[, lapply(.SD, function(col) replace(col, col %in% invalid_values, -99))]
如果想直接修改原表(in-place修改,更省内存),就用:=赋值:
DT[, names(DT) := lapply(.SD, function(col) replace(col, col %in% invalid_values, -99))]
方案2:用across(适用于data.table 1.14.0及以上版本)
新版本的data.table支持across函数,写法更简洁:
# 生成新表 DT_cleaned <- DT[, across(everything(), ~replace(.x, .x %in% invalid_values, -99))] # 直接修改原表 DT[, across(everything(), ~replace(.x, .x %in% invalid_values, -99)) := .SD]
方案3:用fcase(更高效的向量化判断)
如果追求极致性能,推荐用data.table的fcase函数,它是完全向量化的,比replace可能更快:
DT[, names(DT) := lapply(.SD, function(col) fcase(col %in% invalid_values, -99, default = col))]
另外提一句,你原来的循环写法其实语法有问题,正确的循环写法应该是DT[DT == invalid_values[i]] <- -99,但循环在处理大表时效率很低,所以还是上面的向量化方法更好。
内容的提问来源于stack exchange,提问作者SmurfAcco
相关产品推荐
相关产品推荐

