另一个有关data.tables列表的快速data.table问题:
foo <- rep(1:3, times=3)
lorem <- c(20, 30, -10, 405, 70, 20, 35, 50, 30)
df1 <- data.table(foo, lorem)
foo1 <- rep(1:3, times=3)
lorem1 <- c(0, 30, -50, 500, 20, 10, 500, 20, 10)
df2 <- data.table(foo1, lorem1)
setnames(df2, 1:2,c("foo", "lorem"))
df.list <- list(df1, df2)
print(df.list)
[[1]]
foo lorem
1: 1 20
2: 2 30
3: 3 -10
4: 1 405
5: 2 70
6: 3 20
7: 1 35
8: 2 50
9: 3 30
[[2]]
foo lorem
1: 1 0
2: 2 30
3: 3 -50
4: 1 500
5: 2 20
6: 3 10
7: 1 500
8: 2 20
9: 3 10
我正在尝试删除lorem列中的变化超过20倍或为负的所有观察结果。
例如,对于foo == 1(我的id列),由于值(20,405,35)((max = 405 / min = 20)> 20),他的变化将大于20。
这很复杂,因为我必须在40个data.tables的列表上运行它。
我尝试运行以下命令:
> tester <- purrr::map(df.list, function(dat) {
+ dat[dat[, .I[which.max(lorem) / which.min(lorem) < 20], by=foo]$V1]
+ })
>
> print(tester)
[[1]]
foo lorem
1: 1 20
2: 1 405
3: 1 35
4: 2 30
5: 2 70
6: 2 50
7: 3 -10
8: 3 20
9: 3 30
[[2]]
foo lorem
1: 1 0
2: 1 500
3: 1 500
4: 2 30
5: 2 20
6: 2 20
7: 3 -50
8: 3 10
9: 3 10
但是您可以看到,这仅按ID对列表进行了排序。对data.table使用的.I / .SD子集不太熟悉。我如何解决此问题以获得以下输出:
[[1]]
foo lorem
2 30
2 70
2 50
[[2]]
foo lorem
2 30
2 20
2 20
因此,我只保留max(lorem)/ min(lorem)<20或非负数的那些行?
答案 0 :(得分:3)
将list
与lapply
循环后,使用max
和min
创建逻辑表达式,并检查all
的值是否为非负值,分组按“ foo”,然后提取行索引(.I
)以对数据集的行进行子集
lapply(df.list, function(dat) dat[dat[,
.I[all(sign(lorem) >=0) &&(max(lorem) <= 20 * min(lorem))], foo]$V1])
#[[1]]
# foo lorem
#1: 2 30
#2: 2 70
#3: 2 50
#[[2]]
# foo lorem
#1: 2 30
#2: 2 20
#3: 2 20
如果我们使用的是map
中的purrr
library(purrr)
map(df.list, ~ .x[.x[, .I[all(sign(lorem) >= 0) &&
(max(lorem) <= 20 * min(lorem))], foo]$V1])