【发布时间】:2019-08-21 11:51:26
【问题描述】:
我有以下数据
set.seed(42)
dat <- list(data.table(id=1:10, group=rep(1:2, each=5), x=rnorm(10)),
data.table(id=1:10, group=rep(1:2, each=5), x=rnorm(10)))
我想逐个元素并按组应用此功能。
subs = function(x, ..., verbose=FALSE){
L = substitute(list(...))[-1]
mon = data.table(cond = as.character(L))[, skip := FALSE]
for (i in seq_along(L)){
d = eval( substitute(x[cond, verbose=v], list(cond = L[[i]], v = verbose)) )
if (nrow(d)){
x = d
} else {
mon[i, skip := TRUE]
}
}
#print(mon)
return(x)
}
但是,当我运行这段代码时
# works
out <- lapply(1:2, function(h){
res <- list()
d <- dat[[h]]
for(k in 1:2){
g <- d[group==k]
cutoff <- 1
print(cutoff)
res[[k]] <- subs(g, x>cutoff)
}
res
})
我收到无法找到对象cutoff 的错误消息,尽管它打印正确。但是,当我在 lapply() 之外应用相同的 for 循环时,它似乎可以工作。
d1 <- dat[[1]]
s <- list()
for(k in 1:2){
g <- d1[group==k]
cutoff <- 1
s[[k]] <- subs(g, x>cutoff)
}
> s
[[1]]
id group x
1: 1 1 1.370958
[[2]]
id group x
1: 7 2 1.511522
2: 9 2 2.018424
这使我怀疑是 lapply() 中的包含导致错误,但我发现很难看出错误是什么,以及如何修复它。
编辑
具有两个变量的数据:
set.seed(42)
dat <- list(data.table(id=1:10, group=rep(1:2, each=5), x=rnorm(10), y=11:20),
data.table(id=1:10, group=rep(1:2, each=5), x=rnorm(10), y=11:20))
预期结果
[[1]]
id group x y
1: 9 2 2.0184237 19
2: 1 1 1.3709584 11
3: 2 1 -0.5646982 12
4: 3 1 0.3631284 13
5: 4 1 0.6328626 14
6: 5 1 0.4042683 15
[[2]]
id group x y
1: 2 1 2.2866454 12
2: 10 2 1.3201133 20
【问题讨论】:
-
我认为您的函数
subs()不知道对象cutoff,因为您没有通过参数传递它。Substitute返回解析树,但不创建截止?例如,subs = function(x, ..., verbose=FALSE, cutoff = cutoff)和res[[k]] <- subs(g, 1 > cutoff, cutoff = cutoff)将工作编辑:在 lapply 之外,您可以在全局环境中创建它。哪个sub()可以访问那里? -
正确,
subs()传递x>cutoff,因为它是 L 而不是x>1,在subs()的第一行插入browser()并重新运行代码。 -
@Arcoutte,我不太明白。如果可能的话,我希望输入的条件尽可能灵活,以便我可以将
subs()应用于不同的情况。你是说我必须在函数的定义中定义变量? -
我检查并认为你是对的:它创建了一个全局变量。我仍然不明白如何在
lapply()中做到这一点。 -
将
subs中的L更改为L=list(...)和res[[k]]更改为res[[k]] <- subs(g, substitute(x>cutoff)),在subs中适用于一个和两个条件,但我不知道它是否会扩展根据您的实际情况。
标签: r nested data.table lapply