首页 > 解决方案 > 修复由 9 表示的 NA(例如:99、999、9999)匹配 data.table(或 fread)中的列宽

问题描述

文本文件中的数据通常具有代表 NA 的可变长度的 9 序列。也就是说,代表 NA 的 9 的数量取决于每个变量中的字符数。例如:

清除这些值的最佳方法是什么?

请注意,在 中freadna.values=c('99','999')不是一个理想的选择,因为它会破坏 3 位变量中的合法 99 值。

假设我有data.table d, 和两组数字列

cols_2digit <- c('a','b')
cols_3digit <- c('c','d')

如何在每组的所有列中一次用 NA 替换 9 的序列?集的数量是有限的,所以每集一个命令就可以了。

OBS:这些可变长度的 NA 代码让人联想到固定宽度文件 (fwf),即使现代文件以 csv 提供(这可能在列中为 NA 采用标准的“999999”值)。

标签: rdata.tablenafread

解决方案


我们可以set通过循环使用“cols_2digit”或“cols_3digit”中指定的列并更改列中的值

for(j in cols_2digit) set(d, i = which(d[[j]] == '99'), j = j, value = NA_character_)
for(j in cols_3digit) set(d, i = which(d[[j]] == '999'), j = j, value = NA_character_)

或者另一种选择是Map

d[, c(cols_2digit, col2_3digit) := 
     Map(function(dat, y) lapply(dat, function(x) 
         fifelse(x, x == y, NA_character_)), list(.SD[, ..cols_2digit],
                             .SD[, ..cols_3digit]), list('99', '999')) ]

此外,另一种选择是根据最大频率查找列宽,而不是在不同的集合上执行此操作

Mode <- function(x) {
   ux <- unique(x)
   ux[which.max(tabulate(match(x, ux)))]
   }

d[, lapply(.SD, function(x) {
                # get the most frequent column width
                colwidth <-  Mode(nchar(x))
                # if it is max 
                # colwidth <- max(nchar(x))
                # get the elements that are only 9 from start (`^`) to end (`$`)
                i1 <- grepl('^9+$', x) 
                # do the assignment based on the index
                x[i1][nchar(x[i1]) == colwidth] <- NA_character_
                x
              })]

推荐阅读