R 如何删除data.table中包含相同值的3个连续行

R 如何删除data.table中包含相同值的3个连续行,r,data.table,R,Data.table,我在R中有一个数据表,具有以下3个特性 DT_A <- data.table(sid=c(1,1,2,2,2,3,3,2,3,3), date=as.Date(c("2014-06-22","2014-06-23","2014-06-22","2014-06-23", "2014-06-24","2014-06-22", "2014-06-23","2014-06-24","

我在R中有一个数据表,具有以下3个特性

DT_A <- data.table(sid=c(1,1,2,2,2,3,3,2,3,3), date=as.Date(c("2014-06-22","2014-06-23","2014-06-22","2014-06-23", "2014-06-24","2014-06-22",
                                                          "2014-06-23","2014-06-24","2014-06-25","2014-06-26")), 
               Status1 = c("A","B","A","A","B","A","A","A","B","B"))

我如何检查状态1并查看一行中是否有3行具有值a(如第6、7、8行),然后我们将删除这些行?

问题标记为
数据。表
,因此我将尝试给出适当的答案:

with(rle(DT_A$Status1 == "A"), {
    unlist(lapply(which(lengths >= 3), function(i)
        (1+cumsum(lengths)[i-1]):cumsum(lengths)[i]))
})
#[1] 6 7 8
DT_A[!DT_A[, .I[.N == 3 & Status1 == "A"], by = rleid(Status1)]$V1]
其他测试用例 正如所指出的,我的第一个答案(现在已编辑)仅适用于OP提供的给定样本数据集,但在其他测试用例中失败

因此,编辑后的代码将应用于其他一些测试用例

案例B:3行连续的字母
A
B

DT_B <- data.table(
  sid=c(1,1,2,2,2,3,3,2,3,3,3), 
  date=as.Date(c("2014-06-22","2014-06-23","2014-06-22","2014-06-23", "2014-06-24","2014-06-22",
                 "2014-06-23","2014-06-24","2014-06-25","2014-06-26","2014-06-26")), 
  Status1 = c("A","B","A","A","B","A","A","A","B","B","B"))
DT_B
仅删除包含字母
A
(第6至8行)的3个连续行

案例C:无需删除的内容

DT_C <- data.table(
  sid=c(1,1,2,2,2,3,3,2,3,3,3), 
  date=as.Date(c("2014-06-22","2014-06-23","2014-06-22","2014-06-23", "2014-06-24","2014-06-22",
                 "2014-06-23","2014-06-24","2014-06-25","2014-06-26","2014-06-26")), 
  Status1 = c("A","B","A","A","B","A","A","C","B","B","C"))
DT_C
不删除任何行,因为没有3个连续行包含
A

案例D:边缘案例:删除所有行

DT_D <- DT_A[6:8]
DT_D

删除所有行并返回空data.table,因为输入data.table仅包含3行字母
A

问题被标记为
data.table
,因此我将尝试给出适当的答案:

DT_A[!DT_A[, .I[.N == 3 & Status1 == "A"], by = rleid(Status1)]$V1]
其他测试用例 正如所指出的,我的第一个答案(现在已编辑)仅适用于OP提供的给定样本数据集,但在其他测试用例中失败

因此,编辑后的代码将应用于其他一些测试用例

案例B:3行连续的字母
A
B

DT_B <- data.table(
  sid=c(1,1,2,2,2,3,3,2,3,3,3), 
  date=as.Date(c("2014-06-22","2014-06-23","2014-06-22","2014-06-23", "2014-06-24","2014-06-22",
                 "2014-06-23","2014-06-24","2014-06-25","2014-06-26","2014-06-26")), 
  Status1 = c("A","B","A","A","B","A","A","A","B","B","B"))
DT_B
仅删除包含字母
A
(第6至8行)的3个连续行

案例C:无需删除的内容

DT_C <- data.table(
  sid=c(1,1,2,2,2,3,3,2,3,3,3), 
  date=as.Date(c("2014-06-22","2014-06-23","2014-06-22","2014-06-23", "2014-06-24","2014-06-22",
                 "2014-06-23","2014-06-24","2014-06-25","2014-06-26","2014-06-26")), 
  Status1 = c("A","B","A","A","B","A","A","C","B","B","C"))
DT_C
不删除任何行,因为没有3个连续行包含
A

案例D:边缘案例:删除所有行

DT_D <- DT_A[6:8]
DT_D

删除所有行并返回空data.table,因为input data.table仅包含3行字母
A

我假设您在sid定义中出错,并且您的3行都具有sid=3。如果没有,很抱歉,我的回答不起作用。如果是这种情况,解决方案可以是一行:

 DT_A[,.SD[.N < 3 | Status1 != "A",], by = .(sid,Status1)]
DT|A[,.SD[.N<3|Status1!=“A”,]由=(sid,Status1)]
是一个简单的行,可以执行您想要的操作:它选择列Status1中的行数小于3或不同于B的数据(即您要进行的删除选择的否定:至少3 a),然后按sid和Status1进行分组。
希望它能有所帮助,我假设您在sid定义中犯了一个错误,并且您的3行都是sid=3。如果没有,很抱歉,我的回答不起作用。如果是这种情况,解决方案可以是一行:

 DT_A[,.SD[.N < 3 | Status1 != "A",], by = .(sid,Status1)]
DT|A[,.SD[.N<3|Status1!=“A”,]由=(sid,Status1)]
是一个简单的行,可以执行您想要的操作:它选择列Status1中的行数小于3或不同于B的数据(即您要进行的删除选择的否定:至少3 a),然后按sid和Status1进行分组。
希望它有帮助

除了.N==3(或者.N>=3)之外,您还需要检查rleid(x)中的x是否计算为TRUE。另外,x[-w]是个坏主意,因为当w=整数(0)时,结果类似于x[0]。我可能会这样做,
DT_A[,keep:=!(.N>=3L&&Status1==“A”),by=rleid(Status1)][(keep),!“keep”]
或其他什么。Fwiw,db的答案还有第一个问题(检查rle(x)组的长度,但不验证x是否正确)。谢谢,@Frank指出了这些缺陷。已修复并添加了其他测试用例。除了.N==3(或者.N>=3)之外,还需要检查rleid(x)中的x是否计算为TRUE。另外,x[-w]是个坏主意,因为当w=整数(0)时,结果类似于x[0]。我可能会这样做,
DT_A[,keep:=!(.N>=3L&&Status1==“A”),by=rleid(Status1)][(keep),!“keep”]
或其他什么。Fwiw,db的答案还有第一个问题(检查rle(x)组的长度,但不验证x是否正确)。谢谢,@Frank指出了这些缺陷。已修复并添加了其他测试用例。此答案还将删除非连续行。感谢@Uwe的评论。你完全是赖特。我从你的回答中学到了一些东西。实际上是我的条件。这个答案也会删除非连续行。谢谢@Uwe的评论。你完全是赖特。我从你的回答中学到了一些东西。事实上,我的情况也是如此
    sid       date Status1
 1:   1 2014-06-22       A
 2:   1 2014-06-23       B
 3:   2 2014-06-22       A
 4:   2 2014-06-23       A
 5:   2 2014-06-24       B
 6:   3 2014-06-22       A
 7:   3 2014-06-23       A
 8:   2 2014-06-24       C
 9:   3 2014-06-25       B
10:   3 2014-06-26       B
11:   3 2014-06-26       C
DT_D <- DT_A[6:8]
DT_D
   sid       date Status1
1:   3 2014-06-22       A
2:   3 2014-06-23       A
3:   2 2014-06-24       A
DT_D[!DT_D[, .I[.N == 3 & Status1 == "A"], by = rleid(Status1)]$V1]
Empty data.table (0 rows) of 3 cols: sid,date,Status1
 DT_A[,.SD[.N < 3 | Status1 != "A",], by = .(sid,Status1)]