如何在满足某个特定条件时删除一组值?

How to delete a group of values when a certain certain condition is met?

最初的数据是这样的:

obs gr  x1  x2  gender
1   1   0   4   M
2   1   4   13  M
3   1   13  15  M
4   1   15  15  M
5   2   0   1   F
6   2   1   15  F
7   2   15  19  F
8   2   19  30  F
9   2   30  31  F
10  3   0   2   F
11  3   2   4   F
12  3   4   7   F
13  4   0   1   M
14  4   1   14  M
15  4   14  22  M
16  4   22  31  M
17  4   31  31  M
18  4   31  60  M
19  4   60  60  M

我想让数据看起来像这样:在每个组("gr")中,如果任何行中 x1 和 x2 的值相等,则该组中的所有值都将被删除。所以新数据应该是这样的:

obs gr  x1  x2  gender
1   1   0   1   F
2   1   1   15  F
3   1   15  19  F
4   1   19  30  F
5   1   30  31  F
6   2   0   2   F
7   2   2   4   F
8   2   4   7   F

"gr" 列中的数字也应重新排列。即gr中的2变为1gr中的3变为2

谢谢。

这是一种方法。我相信会有更好的方法。首先,我按 gr 对数据进行分组。其次,我检查了 x1x2 中是否有任何行具有相同的值。如果有这样一行,我让R赋值1,否则0。最后用filter做子集。之后,我按照您的要求做了一些更改 gr

group_by(mydf, gr) %>%
mutate(check = ifelse(any(x1 == x2) == TRUE, 1, 0)) %>%
filter(check == 0) %>%
ungroup %>%
mutate(gr = cumsum(c(TRUE, diff(gr) != 0))) %>%
select(-check)

#  obs gr x1 x2 gender
#1   5  1  0  1      F
#2   6  1  1 15      F
#3   7  1 15 19      F
#4   8  1 19 30      F
#5   9  1 30 31      F
#6  10  2  0  2      F
#7  11  2  2  4      F
#8  12  2  4  7      F

更新

多亏了akrun的好心指点,让我学会了简洁的处理方式。

group_by(mydf, gr) %>%
filter(!any(x1 == x2)) %>%
ungroup %>%
mutate(obs = 1:n(),
       gr = as.numeric(factor(gr)))

#  obs gr x1 x2 gender
#1   1  1  0  1      F
#2   2  1  1 15      F
#3   3  1 15 19      F
#4   4  1 19 30      F
#5   5  1 30 31      F
#6   6  2  0  2      F
#7   7  2  2  4      F
#8   8  2  4  7      F

数据

mydf <- structure(list(obs = 1:19, gr = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 
2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L), x1 = c(0L, 4L, 
13L, 15L, 0L, 1L, 15L, 19L, 30L, 0L, 2L, 4L, 0L, 1L, 14L, 22L, 
31L, 31L, 60L), x2 = c(4L, 13L, 15L, 15L, 1L, 15L, 19L, 30L, 
31L, 2L, 4L, 7L, 1L, 14L, 22L, 31L, 31L, 60L, 60L), gender = structure(c(2L, 
2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L), .Label = c("F", "M"), class = "factor")), .Names = c("obs", 
"gr", "x1", "x2", "gender"), class = "data.frame", row.names = c(NA, 
-19L))

这是一个使用 data.table 的选项。

library(data.table)# data.table_1.9.5
setDT(mydf)[,.SD[!any(x1==x2)] , gr][, 
            c('gr', 'obs') := list(rleid(gr), 1:.N)][]
#    gr obs x1 x2 gender
#1:  1   1  0  1      F
#2:  1   2  1 15      F
#3:  1   3 15 19      F
#4:  1   4 19 30      F
#5:  1   5 30 31      F
#6:  2   6  0  2      F
#7:  2   7  2  4      F
#8:  2   8  4  7      F

注意:.SD 可以替换为 .I 以获取行索引,然后将其用于子集。

或使用base R

transform(mydf[with(mydf, !ave(x1==x2, gr, FUN=any)),], 
          obs=seq_along(obs), gr=as.numeric(factor(gr)))