#r #filter #dplyr #subset
#r #Фильтр #dplyr #подмножество
Вопрос:
TLDR: нужно фильтровать человека по двум разным критериям
В основном, учитывая приведенный ниже пример, мне нужно знать, какой человек получил и сыр, и хлеб, и возвращает строки, равные этому. В примере это аблибаба, Мэри и Стив.
Обычно несколько критериев фильтрации в dplyr довольно просты, но это просматривается в разных строках, поэтому я нахожу это довольно сложным. Я придумал длинное решение, но я уверен, что есть более эффективный способ.
Я имею дело с большим набором данных, поэтому важна скорость.
set.seed(1111)
df = data.frame(ID = sample(c("bob","steve","mary","alibaba"),20,replace = TRUE))
set.seed(1311)
df$food = sample(c("cheese","bread","olives"),20, replace = TRUE)
# finding which individuals have both cheese and bread
index = df %>% distinct(ID,food, .keep_all = TRUE) %>%
filter(food == "cheese" | food == "olives") %>%
group_by(ID) %>%
summarise(freq = n()) %>%
filter(freq > 1) %>% {as.vector(.$ID)}
# returning the rows for the individuals that have both cheese and bread
df %>% filter(ID %in% index,food == "cheese" | food == "olives")
Ответ №1:
После группировки по «идентификатору» filter
те группы, в которых есть как «сыр», так и «оливки», оборачиваются all
и в то же время выполняют поэлементный фильтр со вторым выражением ( food %in% c('cheese', 'olives')
)
library(dplyr)
df %>%
group_by(ID) %>%
filter(all(c('cheese', 'olives') %in% food), food %in% c('cheese', 'olives'))
-вывод
# A tibble: 13 x 2
# Groups: ID [3]
# ID food
# <chr> <chr>
# 1 alibaba olives
# 2 steve olives
# 3 steve olives
# 4 steve olives
# 5 alibaba cheese
# 6 steve olives
# 7 steve olives
# 8 mary cheese
# 9 alibaba olives
#10 mary olives
#11 steve cheese
#12 alibaba olives
#13 steve olives
Или другим вариантом, который потенциально быстрее, было бы сначала filter
, а затем выполнить группировку и отфильтровать те группы, которые имеют 2 разных значения в ‘food’
df %>%
filter(food %in% c('cheese', 'olives')) %>%
group_by(ID) %>%
filter(n_distinct(food) == 2)
Или другой вариант с data.table
library(data.table)
i1 <- setDT(df)[, .I[all(c('cheese', 'olives') %in% food) amp; food %in% c('cheese', 'olives')], ID]$V1
df[i1]
Комментарии:
1. Я думаю, что это выглядит хорошо …. не могли бы вы просто объяснить, возможно?
2. @Dasr я обновил сообщение. Надеюсь, это поможет. Если вы можете сказать мне, в чем проблема, я могу вам помочь
3. Все в порядке. Я просто пытался понять первый ответ, который вы дали. Но это работает. Спасибо.