样本数据
data =data.frame(id=c(1,1,1,2,2,2,3,3,3,4,4,4),
score=c(5,7,6,9,8,4,NA,11,3,7,NA,10))
因此在此示例中,如果id的分数等于7,则我想删除这些id以获得新的数据框,例如:
data2 =data.frame(id=c(2,2,2,3,3,3),
score=c(9,8,4,NA,11,3))
我尝试了data[data$score != 7,]
,但这仅适用于一行,不适用于该组。
答案 0 :(得分:3)
使用subset
保留!any(x == 7, na.rm = TRUE)
为TRUE的任何组。这种单线仅使用基数R。
subset(data, !ave(score, id, FUN = function(x) any(x == 7, na.rm = TRUE)))
给予:
id score
4 2 9
5 2 8
6 2 4
7 3 NA
8 3 11
9 3 3
答案 1 :(得分:2)
如果您想要不需要任何软件包的解决方案,则可以尝试:
data[!(data$id %in% data$id[data$score == 7]) , ]
id score
4 2 9
5 2 8
6 2 4
7 3 NA
8 3 11
9 3 3
为了说明一点,当data$id[data$score == 7]
为id
时,score
位会找到7
。然后,当原始数据帧中的%in%
是id
的其中之一时,我们使用data$id %in% data$id[data$score == 7]
查找逻辑向量。然后,用!
将其包围,以删除那些id
。
这里的杀伤力可能很高,但是我们可以对到目前为止提出的所有选择进行基准测试:
library(dplyr)
library(microbenchmark)
microbenchmark(`G. Grothendieck` = subset(data, !ave(score, id, FUN = function(x) any(x == 7, na.rm = TRUE))),
`Nick Criswell` = data[!(data$id %in% data$id[data$score == 7]) , ],
divibisan = data %>%
group_by(id) %>%
filter(!(7 %in% score)),
arg0naut = data %>%
anti_join(data %>% filter(score == 7), by = "id"),
tmfmnk = data %>%
group_by(id) %>%
filter(!any(score == 7, na.rm = TRUE)),
`d.b` = data[!data$id %in% split(data$id, data$score)$`7`,])
Unit: microseconds
expr min lq mean median uq max neval
G. Grothendieck 160.001 177.455 189.4648 185.4545 195.6370 269.576 100
Nick Criswell 37.819 45.091 52.2820 53.8190 57.2130 93.576 100
divibisan 443.636 456.000 480.1211 464.0000 489.4545 904.726 100
arg0naut 733.091 757.818 806.7143 766.0600 805.3325 1543.755 100
tmfmnk 444.121 457.939 704.8916 463.0300 479.5150 22332.079 100
d.b 103.759 114.424 125.3291 122.1825 131.8800 202.182 100
答案 2 :(得分:1)
data[!data$id %in% split(data$id, data$score)$`7`,]
# id score
#4 2 9
#5 2 8
#6 2 4
#7 3 NA
#8 3 11
#9 3 3
答案 3 :(得分:0)
我们可以做到:
library(dplyr)
data %>%
anti_join(data %>% filter(score == 7), by = "id")
输出:
id score
1 2 9
2 2 8
3 2 4
4 3 NA
5 3 11
6 3 3
答案 4 :(得分:0)
在dplyr
中,我们可以在每个组中group_by
和filter
中是否存在!
中的7
score
变量:
library(dplyr)
data %>%
group_by(id) %>%
filter(!(7 %in% score))
# A tibble: 6 x 2
# Groups: id [2]
id score
<dbl> <dbl>
1 2 9
2 2 8
3 2 4
4 3 NA
5 3 11
6 3 3
答案 5 :(得分:0)
另一种dplyr
可能性:
data %>%
group_by(id) %>%
filter(!any(score == 7, na.rm = TRUE))
id score
<dbl> <dbl>
1 2 9
2 2 8
3 2 4
4 3 NA
5 3 11
6 3 3
或者:
data %>%
group_by(id) %>%
filter(!any(cumsum(ifelse(is.na(score), 0, score) == 7) >= 1))
或与base相同:
data[!ave(data$score, data$id, FUN = function(x) any(cumsum(ifelse(is.na(x), 0, x) == 7) >= 1)), ]
id score
4 2 9
5 2 8
6 2 4
7 3 NA
8 3 11
9 3 3
或类似于@G的可能性。格洛腾迪克,但没有subset()
:
data[!ave(data$score, data$id, FUN = function(x) any(x == 7, na.rm = TRUE)), ]