假设我有一个如下所示的数据表:
library(data.table)
N = 10
x = data.table(id = 1:N,
segm = sample(c("A","B","C"),N,replace=T), r = rnorm(N,20,5),
aa = sample(0:1,N,replace=T), ab = sample(0:1,N,replace=T),
ba = sample(0:1,N,replace=T), bb = sample(0:1,N,replace=T))
我想知道如何替换NA
的1个值,但仅限于列aa
,ab
,ba
和{{1}使用数据表包。我知道如何使用数据框执行此操作。
我尝试使用以下内容:
bb
但我收到了错误:f = c("aa","ab","ba","bb")
x[,f,with=F][x[,f,with=F]==1] <- "NA"
总而言之,我的问题是:如何在数据表的多个列上同时进行子集和分配。
代码行:
Error in [<-.data.table(*tmp*, , f, with = F, value = list(aa = c("0", : unused argument (with = F)
只是不起作用。为什么呢?
任何帮助都表示赞赏。
答案 0 :(得分:4)
对于这种特殊情况,可以通过另一种方式实现这一目标:
x[, (f) := lapply(.SD, function(x) x * (x | NA)), .SDcols=f]
我们在此使用TRUE | NA = TRUE
和FALSE | NA = NA
这一事实。 (
的LHS中的:=
将其视为表达式(而不是变量名称),因此对其进行求值以获取其中包含的列。指定.SDcols
只为.SD
提供f
,我们想要的是什么。我们通过引用来应用函数的这个hack来替换每一列。
DT[f == 1, f := NA]
不起作用,因为:
让我们将您的表达式写为DT[i, LHS := RHS]
。作为表达式的i
在DT
的范围内进行评估。 [.data.table
尝试在f
范围内找到列DT
,因为没有任何内容,它会尝试在调用范围内找到并获取值存储在其中,然后变为:c("aa", "ab", "ba", "bb") == 1
。此评估结果为FALSE, FALSE, FALSE, FALSE
,结果为空data.table
- j
中的作业无效。
另请注意我的答案中(
中的LHS
。这样我们仍然可以方便地使用DT[, f := val]
f
列名称。{/ p>
答案 1 :(得分:3)
在这里使用for()
循环没有任何问题。
鉴于您的问题的性质,在四列中的每一列中操作不同的行子集,您将需要使用某些类型的循环;您也可以构建一个明确的版本,以便您充分利用 data.table 的修改引用:=
运算符。
for (i in f)
x[get(i)==1, (i):=NA]
x
# id segm r aa ab ba bb
# 1: 1 C 15.203246 NA NA 0 0
# 2: 2 B 23.536583 NA 0 0 NA
# 3: 3 A 16.404203 NA 0 NA 0
# 4: 4 A 18.673618 0 0 NA NA
# 5: 5 C 30.528967 NA 0 NA NA
# 6: 6 A 18.887781 0 NA NA NA
# 7: 7 C 24.476124 0 0 NA NA
# 8: 8 B 26.862686 0 0 NA 0
# 9: 9 C 9.047837 0 0 0 NA
# 10: 10 C 17.532379 0 0 NA NA