我有一个虚拟数据集:
abc <- data.table(a = c("NA", "bc", "x"), b = c(1, 2, 3), c = c("n", "NA", "NA"))我试图用标准NA替换"NA“;使用data.table。我试过:
for(i in names(abc)) (abc[which(abc[[i]] == "NA"), i := NA])
for(i in names(abc)) (abc[which(abc[[i]] == "NA"), i := NA_character_])
for(i in names(abc)) (set(abc, which(abc[[i]] == "NA"), i, NA))尽管如此,我还是得到了:
abc$a
"NA" "bc" "x"我遗漏了什么?
编辑:,我在这个问题中尝试了@ type.convert()的回答,这个问题利用了type.convert()。(谢谢弗兰克;我不知道这种模糊但有用的函数)在type.convert()的文档中提到:“这主要是read.table的一个辅助函数。”所以我想彻底测试一下。当您有一个填充"NA“(NA字符串)的完整列时,此函数具有小的副作用。在这种情况下,type.convert()正在将列转换为逻辑列。对于这种情况,abc将是:
abc <- data.table(a = c("NA", "bc", "x"), b = c(1, 2, 3), c = c("n", "NA", "NA"), d = c("NA", "NA", "NA"))EDIT2:用于总结原始问题中存在的代码的:
for(i in names(abc)) (set(abc, which(abc[[i]] == "NA"), i, NA))工作良好,但只适用于当前最新版本的data.table (> 1.11.4)。因此,如果一个人正面临这个问题,那么更新data.table并使用此代码比使用type.convert()更好
发布于 2018-08-06 17:17:53
我会这么做..。
chcols = names(abc)[sapply(abc, is.character)]
abc[, (chcols) := lapply(.SD, type.convert, as.is=TRUE), .SDcols=chcols]产额
> str(abc)
Classes ‘data.table’ and 'data.frame': 3 obs. of 3 variables:
$ a: chr NA "bc" "x"
$ b: num 1 2 3
$ c: chr "n" NA NA
- attr(*, ".internal.selfref")=<externalptr> 您的set代码无法工作,因为它创建了一个名为“i”的列;正如@AdamSampson所指出的,您的代码已经起作用了。(注: OP从data.table 1.10.4-3升级到1.11.4,之后在他们的公司升级为1.11.4)
所以我想彻底测试一下。当您有一个填充"NA“(NA字符串)的完整列时,此函数具有小的副作用。在这种情况下,
type.convert()正在将列转换为逻辑列。
哦对了。对于这个问题,您最初的方法更安全:
# op's new example
abc <- data.table(a = c("NA", "bc", "x"), b = c(1, 2, 3), c = c("n", "NA", "NA"), d = c("NA", "NA", "NA"))
# op's original code
for(i in names(abc))
set(abc, which(abc[[i]] == "NA"), i, NA)附带注意: NA具有逻辑类型;通常,当将不一致类型的值赋值给列时,data.table会发出警告,但我猜它们是在NAs的例外情况下编写的:
DT = data.table(x = 1:2)
DT[1, x := NA]
# no problem, even though x is int and NA is logi
DT = data.table(x = 1:2)
DT[1, x := TRUE]
# Warning message:
# In `[.data.table`(DT, 1, `:=`(x, TRUE)) :
# Coerced 'logical' RHS to 'integer' to match the column's type. Either change the target column ['x'] to 'logical' first (by creating a new 'logical' vector length 2 (nrows of entire table) and assign that; i.e. 'replace' column), or coerce RHS to 'integer' (e.g. 1L, NA_[real|integer]_, as.*, etc) to make your intent clear and for speed. Or, set the column type correctly up front when you create the table and stick to it, please.发布于 2018-08-06 17:49:25
我真的很喜欢Frank的反应,但我想添加到它中,因为它假设您只对字符向量执行更改。我也将尝试包括一些关于“为什么”它工作的信息。
要替换所有NA,您可以这样做:
chcols = names(abc)
abc[,(chcols) := lapply(.SD, function(x) ifelse(x == "NA",NA,x)),.SDcols = chcols]让我们分析一下我们在这里做什么。
我们正在查看abc中的每一行(因为在第一个逗号之前没有任何内容)。
下一个逗号后面是列。让我们把它拆开。
我们正在将结果放入chcols中列出的所有列中。(chcols)告诉data.table方法来计算chcols对象中的名称向量。如果省略括号并使用chcols,它将尝试将结果存储在一个名为chcols的列中,而不是使用您想要的列名。
.SD正在返回一个data.table,其中包含.SDcols中列出的每个列的结果(在我的示例中,它返回所有列.)。但是我们想一次评估一个列。因此,我们使用lapply对.SD中的每一列一次应用一个函数。
您可以使用任何将返回正确值的函数。弗兰克用type.convert。我使用一个匿名函数来计算ifelse语句。我使用ifelse,因为它计算并返回整个向量/列。
您已经知道如何使用:=替换适当的值。
在下一篇专栏之后,您可以放置by信息,也可以放置其他选项。我们将以.SDcols的形式添加其他选项。
我们需要放置一个.SDcols = chcols来告诉data.table要在.SD中包含哪些列。我的代码正在计算所有的列,所以如果您不使用.SDcols,那么我的代码仍然可以工作。但是,不使用本专栏是一种坏习惯,因为如果您更改为只对某些列进行评估,那么您将来可能会浪费时间。例如,Frank的示例只计算字符类中的列。
发布于 2018-08-08 08:36:25
以下是另外两种方法:
底座
library(data.table)
abcd <- data.table(a = c("NA", "bc", "x"), b = c(1, 2, 3),
c = c("n", "NA", "NA"), d = c("NA", "NA", "NA"))
for (col in names(abcd)) abcd[get(col) == "NA", (col) := NA]
abcd[]a b c d 1: <NA> 1 n <NA> 2: bc 2 <NA> <NA> 3: x 3 <NA> <NA>
加入时更新
在这里,data.table对变量类型相当严格。
abcd <- data.table(a = c("NA", "bc", "x"), b = c(1, 2, 3),
c = c("n", "NA", "NA"), d = c("NA", "NA", "NA"))
for (col in names(abcd))
if (is.character(abcd[[col]]))
abcd[.("NA", NA_character_), on = paste0(col, "==V1"), (col) := V2][]
abcda b c d 1: <NA> 1 n <NA> 2: bc 2 <NA> <NA> 3: x 3 <NA> <NA>
https://stackoverflow.com/questions/51712526
复制相似问题