首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将" NA“(NA字符串)替换为NA inplace data.table

将" NA“(NA字符串)替换为NA inplace data.table
EN

Stack Overflow用户
提问于 2018-08-06 17:05:45
回答 3查看 836关注 0票数 0

我有一个虚拟数据集:

代码语言:javascript
复制
abc <- data.table(a = c("NA", "bc", "x"), b = c(1, 2, 3), c = c("n", "NA", "NA"))

我试图用标准NA替换"NA“;使用data.table。我试过:

代码语言:javascript
复制
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))

尽管如此,我还是得到了:

代码语言:javascript
复制
abc$a 
"NA" "bc" "x"

我遗漏了什么?

编辑:,我在这个问题中尝试了@ type.convert()的回答,这个问题利用了type.convert()。(谢谢弗兰克;我不知道这种模糊但有用的函数)在type.convert()的文档中提到:“这主要是read.table的一个辅助函数。”所以我想彻底测试一下。当您有一个填充"NA“(NA字符串)的完整列时,此函数具有小的副作用。在这种情况下,type.convert()正在将列转换为逻辑列。对于这种情况,abc将是:

代码语言:javascript
复制
abc <- data.table(a = c("NA", "bc", "x"), b = c(1, 2, 3), c = c("n", "NA", "NA"), d = c("NA", "NA", "NA"))

EDIT2:用于总结原始问题中存在的代码的

代码语言:javascript
复制
for(i in names(abc)) (set(abc, which(abc[[i]] == "NA"), i, NA))

工作良好,但只适用于当前最新版本的data.table (> 1.11.4)。因此,如果一个人正面临这个问题,那么更新data.table并使用此代码比使用type.convert()更好

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-08-06 17:17:53

我会这么做..。

代码语言:javascript
复制
chcols = names(abc)[sapply(abc, is.character)]
abc[, (chcols) := lapply(.SD, type.convert, as.is=TRUE), .SDcols=chcols]

产额

代码语言:javascript
复制
> 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()正在将列转换为逻辑列。

哦对了。对于这个问题,您最初的方法更安全:

代码语言:javascript
复制
# 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的例外情况下编写的:

代码语言:javascript
复制
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.
票数 5
EN

Stack Overflow用户

发布于 2018-08-06 17:49:25

我真的很喜欢Frank的反应,但我想添加到它中,因为它假设您只对字符向量执行更改。我也将尝试包括一些关于“为什么”它工作的信息。

要替换所有NA,您可以这样做:

代码语言:javascript
复制
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的示例只计算字符类中的列。

票数 1
EN

Stack Overflow用户

发布于 2018-08-08 08:36:25

以下是另外两种方法:

底座

代码语言:javascript
复制
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对变量类型相当严格。

代码语言:javascript
复制
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][]
abcd

a b c d 1: <NA> 1 n <NA> 2: bc 2 <NA> <NA> 3: x 3 <NA> <NA>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51712526

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档