r按data.table中的组评估条件以过滤行,数据结构:data.tables列表

时间:2019-11-15 20:24:19

标签: r filter data.table

另一个有关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或非负数的那些行?

1 个答案:

答案 0 :(得分:3)

listlapply循环后,使用maxmin创建逻辑表达式,并检查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])