处理'错误'条目和data.table中的NA用其他表中的条目替换它们

时间:2015-01-01 20:07:03

标签: r data.table na

我在使用闪亮和handsontable.js的更广泛的应用程序的上下文中使用data.table。这是应用程序的这一部分的流程:

  1. 我使用数字列在浏览器上发布data.table,使用handontable&有光泽。这在屏幕上呈现。
  2. 用户更改值,每次发生这种情况时,都会返回带有数据的新data.table。
  3. 问题在于错误管理,特别是如果用户意外地键入了一个字符。

    我的目标是更正用户的错误,将输入字符的单个单元格值替换为原始副本中的值(仅此单元格可能包含有效更改,以便在应用程序的稍后阶段保存)

    可悲的是,我无法找到解决此问题的有效方法。这是我的代码和可重复的样本:

    # I generate a sample datatable
    originTable = data.table( Cat = LETTERS[1:5],
    Jan=1:5,
    Feb=sample(1:5),
    Mar=sample(1:5),
    Apr=sample(1:5),
    May=sample(1:5))
    
    # I take a full copy & to simulate the effect of a character key in by mistake I convert
    # the entire column to character
    dt_ <- copy(originTable)
    dt_[,Jan := as.character(Jan)]
    
    # "q" entered by mistake by the user - 
    dt_[[5,2]] <- "q"
    
    # This is what I get back:
       Cat Jan Feb Mar Apr May
    1:   A   1   1   2   4   4
    2:   B   2   5   4   2   2
    3:   C   3   4   3   1   5
    4:   D   4   3   5   5   1
    5:   E   q   2   1   3   3
    

    现在我的代码尝试修复此问题:

    valCols <- month.abb[1:5]
    for (j in  valCols)
          set(dt_,  
            i = NULL,
            j = j, 
            value= as.numeric(as.character(dt_[[j]])))
    

    这给了我一个带有NA值的data.table(代替错误输入的字符 - 在我忽略的位置)。

    要替换我使用以下代码的值

    for (j in  valCols)
       set(dt_,  
        i = which(is.na(dt_[[j]])),
        j = j, 
        value= as.numeric(originTable[[j]]))
    

    但它不起作用:它找到正确的列,但忽略i值并复制originTable[1,j]而不是originTable[i,j]中包含的值。在示例中,dt_ [5,2]将得到1(定位为originTable [1,2]而不是5。

    换句话说,我希望as.numeric(originTable[[j]])(隐式地)和i(显式)看到j子集。 公平地说,警告告诉我发生了什么:

    Warning message:
    In set(dt_, i = which(is.na(dt_[[j]])), j = j, value = as.numeric(originTable[[j]])) :
      Supplied 5 items to be assigned to 1 items of column 'Jan' (4 unused)
    

    但我仍然没有解决我的问题。

    我已经阅读了无数明显相似的SO帖子,但遗憾的是无济于事(可能因为NA处理在最近的版本中已经发展,而较旧的答案不再完全反映最佳实践)。另外,基于非NA的解决方案同样可以接受。感谢

1 个答案:

答案 0 :(得分:0)

尝试以下方法:

# use your criteria to determine what the incorrect values are in each column
wrongs = lapply(dt_[, !"Cat", with = F], function(x) which(is.na(as.numeric(x))))

# now substitute
for (n in names(wrongs)) dt_[wrongs[[n]], (n) := originTable[[n]][wrongs[[n]]]]

dt_
#   Cat Jan Feb Mar Apr May
#1:   A   1   2   5   2   4
#2:   B   2   4   3   4   5
#3:   C   3   3   2   5   2
#4:   D   4   1   1   1   1
#5:   E   5   5   4   3   3