2016-10-28 1 views
0

Учитывая фрейм данных входа,Как объединить трубы magrittr и% in% внутри функции предиката dplyr :: filter?

library(dplyr) 
(df <- data_frame(id = c(1,1,1,2,2,3), y = letters[1:6])) 
# # A tibble: 6 × 2 
#  id  y 
# <dbl> <chr> 
# 1  1  a 
# 2  1  b 
# 3  1  c 
# 4  2  d 
# 5  2  e 
# 6  3  f 

Допустит, один хочет получить подмножество df[, c("id", "y")] только два наиболее распространенных идентификаторов, которые id1 и 2:

df %>% group_by(id) %>% tally %>% arrange(desc(n)) %>% head(2) %>% .$id %>% print -> ids #* 
# [1] 1 2 

Вопрос: Есть ли способ использовать трубку в функции предиката внутри filter в жилах:

df %>% filter(
    id %in% df %>% group_by(id) %>% tally %>% arrange(desc(n)) %>% head(2) %>% .$id ) 
# Error: no applicable method for 'group_by_' applied to an object of class "logical" 

df %>% filter(
    id %in% (df %>% group_by(id) %>% tally %>% arrange(desc(n)) %>% head(2) %>% .$id) ) 
# Error: cannot handle 

df %>% filter(
    id %in% {df %>% group_by(id) %>% tally %>% arrange(desc(n)) %>% head(2) %>% .$id} ) 
# Error: cannot handle 

?

Я имею в виду, что последние два предиката, кажется, работают, как ожидается, за пределами filter:

df$id %in% (df %>% group_by(id) %>% tally %>% arrange(desc(n)) %>% head(2) %>% .$id) 
# [1] TRUE TRUE TRUE TRUE TRUE FALSE 
df$id %in% {df %>% group_by(id) %>% tally %>% arrange(desc(n)) %>% head(2) %>% .$id} 
# [1] TRUE TRUE TRUE TRUE TRUE FALSE 

Side Примечание: Я знаю, что мог использовать временную переменную ids:

df %>% filter(id %in% ids) # *ids <- c(1,2) 

или я мог бы использовать *_join:

df %>% inner_join(
    df %>% group_by(id) %>% tally %>% arrange(desc(n)) %>% head(2) %>% select(-n)) 

Оба дают ожидаемый результат:

# # A tibble: 5 × 2 
#  id  y 
# <dbl> <chr> 
# 1  1  a 
# 2  1  b 
# 3  1  c 
# 4  2  d 
# 5  2  e 

ответ

3

Не сделать этот сложный для своего собственного блага.

ids <- (df %>% count(id) %>% arrange(n) %>% tail(2))$id 
filter(df, id %in% ids) 
+0

согласны с тем, что поисковые запросы OP для overkill с 'dplyr' :) –

+0

Спасибо за ваш ответ. Однако это не отличается от примечания стороны № 1 (?). Мой вопрос заключается не в том, чтобы легко выбрать 1-й два общих идентификатора (= это только пример), но и об общей возможности использовать трубы внутри предикатных выражений 'filter' (или' filter_'?). Возможно, _question_ немного переборщил с точки зрения длины и отсутствия ясности, я мог бы согласиться и посидеть, если это так. :) Но трубы - мне, как не-программисту, предлагают несколько преимуществ по сравнению со стандартными обозначениями, например, лучше отображать хотя бы процесс, лучше читать и интерпретировать другие и т. Д. Хмм, и именно поэтому я и спросил. – lukeA

+0

Вы можете превратить это в один лайнер: 'filter (df, id% in% (df%>% count _ (" id ")%>% arr_ _ (" n ")%>% tail (2)) [[ "id"]])), но любой коэффициент удобочитаемости полностью утрачен. Просто пойдите с временной переменной. –

1

Можно пойти на непрерывной цепочки, но не торчит слишком много dplyr/filter, поскольку существуют и другие решения - по-прежнему совместимы с %>%:

df %>% 
    group_by(id) %>% 
    tally %>% 
    arrange(desc(n)) %>% 
    head(2) %>% 
    .$id %>% 
    is.element(df$id, .) %>% 
    subset(df, .) 

Source: local data frame [5 x 2] 

    id  y 
    (dbl) (chr) 
1  1  a 
2  1  b 
3  1  c 
4  2  d 
5  2  e 

Цепочки, а затем обертывание цепи может быть беспорядочным, когда цепь становится длинной.

Для такого reuslt я предпочел бы пойти на основание R один лайнер:

df[df$id %in% as.integer(names(tail(sort(table(df$id)),2))),]