我有一个看起来像这样的df:
ID value
1 A
2 C
3 A
4 B
5 C
6 B
7 A
8 B
我需要获取成对的行的子集,其中第一行的值为A,然后是行的值为B。结果应如下所示:
ID value
3 A
4 B
7 A
8 B
感谢您的帮助!
在dplyr
中,我们可以使用lag
和lead
获取上一个和下一个值。
library(dplyr)
df %>%
filter(value == "A" & lead(value) == "B" | value == "B" & lag(value) == "A")
# ID value
#1 3 A
#2 4 B
#3 7 A
#4 8 B
类似地在data.table
中,我们可以使用shift
:
library(data.table)
setDT(df)[value == "A" & shift(value, type = "lead") == "B" |
value == "B" & shift(value) == "A"]
数据
df <- structure(list(ID = 1:8, value = structure(c(1L, 3L, 1L, 2L,
3L, 2L, 1L, 2L), .Label = c("A", "B", "C"), class = "factor")),
class = "data.frame", row.names = c(NA, -8L))
这是我不太优雅的解决方案。我使用sapply()
手动遍历行,然后使用ifelse()
查找所需的对AB
。因此,如果下一个值是A
,则B
在该对中,但是对于具有TRUE
的行,它仅给出A
,因此我进行了第二个条件检查B
是否在该对中。我一直在寻找B
的先前值,如果它是A
,那么我们有一对。结果,我得到具有res
值的向量(新列)T/F
。现在,我要做的就是只选择带有T
的行。最后是一些化妆品。
df$res <- sapply(1:nrow(df), function(x) ifelse((df[x,2]=='A' & df[x+1,2]=='B') | (df[x,2]=='B' & df[x-1,2]=='A'),TRUE,FALSE))
df <- df[df$res==T,]
df$res <- NULL
df <- df[complete.cases(df),]
df
ID value
3 3 A
4 4 B
7 7 A
8 8 B