【问题标题】:Subset until the condition is met (including it) by group data.table子集,直到通过组 data.table 满足条件(包括它)
【发布时间】:2017-07-13 09:30:49
【问题描述】:

我想通过这样做来对我的 data.table 进行子集化:通过对 idgroup 进行分组,在满足条件时将第一行放到行中。这意味着如果在第 3 行满足条件,我想保留第 1,2 和 3 行。

数据示例:

    id time group
 1:  1    0     1
 2:  1   20     1
 3:  1    0     2
 4:  1   40     2
 5:  2    0     1
 6:  2   35     1
 7:  2   50     1
 8:  3    0     1
 9:  3   10     1
10:  3   20     1
11:  3    0     2
12:  3   25     2
13:  3   45     2

条件是:time > 30,所以预期的结果是:

    id time group
 1:  1    0     2
 2:  1   40     2
 3:  2    0     1
 4:  2   35     1
 5:  3    0     2
 6:  3   25     2
 7:  3   45     2

我试过了:df[1:which(time >30)[1], .SD, by = .(id, group)]

但它会返回:

   id group time
1:  1     1    0
2:  1     1   20
3:  1     2    0
4:  1     2   40

数据:

structure(list(id = c(1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3), 
               time = c(0, 20, 0, 40, 0, 35, 50, 0, 10, 20, 0, 25, 45), 
               group = c(1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 2)), .Names = c("id", 
                                                                             "time", "group"), row.names = c(NA, -13L), class = c("data.table", 
                                                                                                                                  "data.frame"))

UPDATE 显示 akrun 对另一个数据集的回答的预期行为:

数据:

> dftest
     patientid groupe arret dateConsult lag_dateConsult temps abst temps_cum
1: 0303H233457      2     1  2011-10-05            <NA>     0    1         0
2: 0303H233457      2     1  2011-11-09      2011-10-05    35    1        35
3: 0303H233457      2     1  2011-12-21      2011-11-09    42    1        77
4: 0303H233457      2     1  2012-01-30      2011-12-21    40    1       117
5: 0303H233457      2     1  2012-04-18      2012-01-30    79    1       196
6: 0303H233457      2     1  2012-08-27      2012-04-18   131    1       327
7: 0303H233457      4     1  2012-11-19            <NA>     0    1         0
8: 0303H233457      4     1  2013-01-07      2012-11-19    49    1        49

我得到了什么:

> dftest[dftest[, .I[seq(which(temps_cum > 30))], .(patientid, groupe)]$V1]
     patientid groupe arret dateConsult lag_dateConsult temps abst temps_cum
1: 0303H233457      2     1  2011-10-05            <NA>     0    1         0
2: 0303H233457      2     1  2011-11-09      2011-10-05    35    1        35
3: 0303H233457      2     1  2011-12-21      2011-11-09    42    1        77
4: 0303H233457      2     1  2012-01-30      2011-12-21    40    1       117
5: 0303H233457      2     1  2012-04-18      2012-01-30    79    1       196
6: 0303H233457      4     1  2012-11-19            <NA>     0    1         0
7: 0303H233457      4     1  2013-01-07      2012-11-19    49    1        49

预期结果:

     patientid groupe arret dateConsult lag_dateConsult temps abst temps_cum
1: 0303H233457      2     1  2011-10-05            <NA>     0    1         0
2: 0303H233457      2     1  2011-11-09      2011-10-05    35    1        35
3: 0303H233457      4     1  2012-11-19            <NA>     0    1         0
4: 0303H233457      4     1  2013-01-07      2012-11-19    49    1        49

数据:

structure(list(patientid = c("0303H233457", "0303H233457", "0303H233457", 
                             "0303H233457", "0303H233457", "0303H233457", "0303H233457", "0303H233457"
), groupe = c(2, 2, 2, 2, 2, 2, 4, 4), arret = c(1, 1, 1, 1, 
                                                 1, 1, 1, 1), dateConsult = structure(c(15252, 15287, 15329, 15369, 
                                                                                        15448, 15579, 15663, 15712), class = "Date"), lag_dateConsult = structure(c(NA, 
                                                                                                                                                                    15252, 15287, 15329, 15369, 15448, NA, 15663), class = "Date"), 
temps = c(0, 35, 42, 40, 79, 131, 0, 49), abst = c(1, 1, 
                                                   1, 1, 1, 1, 1, 1), temps_cum = c(0, 35, 77, 117, 196, 327, 
                                                                                    0, 49)), .Names = c("patientid", "groupe", "arret", "dateConsult", 
                                                                                                        "lag_dateConsult", "temps", "abst", "temps_cum"), class = c("data.table", 
                                                                                                                                                                    "data.frame"), row.names = c(NA, -8L))

【问题讨论】:

  • 如果你的意思是 dftest[dftest[, .I[seq(which(temps_cum &gt; 30)[1])], .(patientid, groupe)]$V1] 它对我有用
  • @akrun 是的,这就是我所期待的。但是我的完整数据集出现了这个错误:Error in seq.default(which(temps_cum &gt; 30)[1]) : 'from' cannot be NA, NaN or infinite,请问是什么原因导致的?
  • 请检查每组是否只有一个元素,并且该元素不符合temps_cum &gt; 30的条件,在这种情况下,也许您可​​以使用if/else条件dftest[, if(any(temps_cum &gt; 30)) .I[seq(which(temps_cum &gt; 30)[1])], .(patientid, groupe)]
  • @akrun 是的,我在运行您的答案之前检查了它:summary 告诉我min 是 2(当我用.N 按组计数时)并且range 正在返回:@ 987654342@。添加if纠正错误非常感谢。

标签: r data.table subset


【解决方案1】:

按'id'、'group'分组后,得到'time'大于30的行索引,对行进行子集化

df1[df1[, .I[seq(which(time > 30))], .(id, group)]$V1]

如果我们还需要直到“时间”大于 30 的最后一行

df1[df1[, .I[seq(tail(which(time > 30), 1))], .(id, group)]$V1]
#   id time group
#1:  1    0     2
#2:  1   40     2
#3:  2    0     1
#4:  2   35     1
#5:  2   50     1
#6:  3    0     2
#7:  3   25     2
#8:  3   45     2

【讨论】:

  • 一如既往的魅力,我会尽快接受答案
  • 很抱歉再次打扰您,但我的真实数据有一​​个奇怪的行为,并且结果不是预期的,您是否有可能检查它不能按预期工作的子集?
  • @MbrMbr 您能否用一个显示错误的小示例更新您的帖子
  • 我更新了帖子。告诉我你是否有同样的问题。
猜你喜欢
  • 1970-01-01
  • 2015-07-28
  • 2014-01-23
  • 1970-01-01
  • 2012-01-22
  • 2019-11-10
  • 2014-10-18
  • 2021-12-24
  • 1970-01-01
相关资源
最近更新 更多