在 data.table 中处理 'wrong' 个条目和 NA,用其他 table 中的条目替换它们
handling 'wrong' entries and NAs in a data.table substituting them with entries from other table
我在使用 shiny 和 handsontable.js 的更广泛应用程序的上下文中使用 data.table。这是应用程序这部分的流程:
- 我使用 handsontable & shiny 在浏览器上发布了一个带有数字列的 data.table。这是在屏幕上呈现的。
- 用户更改值,每次发生这种情况时都会返回一个新的 data.table 和数据。
问题在于错误管理,特别是如果用户不小心键入了一个字符。
我的objective是为了纠正用户的错误,将输入字符的单个单元格值替换为原始副本中的值(只有这个单元格,因为其他单元格可能包含要保存在应用程序的后期阶段)。
遗憾的是,我找不到解决此问题的有效方法。这是我的代码和可重现的示例:
# 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]])))
这给了我一个 data.table,在某处有一个 NA 值(代替错误输入的字符 - 在我忽略的位置)。
为了替换我使用以下代码的值
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 的解决方案同样可以接受。谢谢
尝试以下操作:
# use your criteria to determine what the incorrect values are in each column
wrongs = lapply(dt_[, !"Cat"], 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
我在使用 shiny 和 handsontable.js 的更广泛应用程序的上下文中使用 data.table。这是应用程序这部分的流程:
- 我使用 handsontable & shiny 在浏览器上发布了一个带有数字列的 data.table。这是在屏幕上呈现的。
- 用户更改值,每次发生这种情况时都会返回一个新的 data.table 和数据。
问题在于错误管理,特别是如果用户不小心键入了一个字符。
我的objective是为了纠正用户的错误,将输入字符的单个单元格值替换为原始副本中的值(只有这个单元格,因为其他单元格可能包含要保存在应用程序的后期阶段)。
遗憾的是,我找不到解决此问题的有效方法。这是我的代码和可重现的示例:
# 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]])))
这给了我一个 data.table,在某处有一个 NA 值(代替错误输入的字符 - 在我忽略的位置)。
为了替换我使用以下代码的值
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 的解决方案同样可以接受。谢谢
尝试以下操作:
# use your criteria to determine what the incorrect values are in each column
wrongs = lapply(dt_[, !"Cat"], 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