【问题标题】:r Evaluate condition by group in data.table to filter rows, data structure: list of data.tablesr 在data.table中按组评估条件以过滤行,数据结构:data.tables列表
【发布时间】:2020-03-12 00:43:33
【问题描述】:

另一个与 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,因为值 (20, 405, 35), (max = 405 / min = 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)

【问题讨论】:

    标签: r filter data.table


    【解决方案1】:

    在用lapply 循环list 之后,用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
    

    如果我们使用来自purrrmap

    library(purrr)
    map(df.list, ~ .x[.x[, .I[all(sign(lorem) >= 0) &&
              (max(lorem) <= 20 * min(lorem))], foo]$V1])
    

    【讨论】:

    • 可以使用最小值检查符号问题,例如rbindlist(df.list, id="tab")[, if (((mn &lt;- min(lorem)) &gt;= 0) &amp;&amp; max(lorem) &lt;= 20*mn) .SD, by=.(tab, foo)]
    • 我很高兴你在 stackoverflow 上! @akrun!! :) 非常感谢您对我所有问题的帮助。我正在从事经济学和心理学方面的研究,但慢慢后悔没有参加更多的计算机科学课程^^ 感谢您再次提供帮助!
    • 嗨,akrun,是的,我创建了新帐户以供工作使用(因为我现在不想从那里登录)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-21
    • 1970-01-01
    • 2020-09-01
    • 2021-11-25
    • 2018-04-30
    • 2015-05-12
    相关资源
    最近更新 更多