2017-02-23 69 views
0

Это основано на ответе на предыдущий question.Найти общие элементы из нескольких категорий в рамках dataframe?

df 
year code 
2009 a 
2009 a 
2009 b 
2010 b 
2010 b 
2011 b 
2011 c 
2011 c 

Я хочу выбрать коды, общие для всех лет в пределах df. Здесь это «b». Одним из решений является:

Reduce(intersect, list(unique(df$code[df$year==2009]), 
         unique(df$code[df$year==2010]), 
         unique(df$code[df$year==2011]))) 

На практике ДФ содержит около 15 лет, тысячи кодов, миллионы строк и несколько столбцов. Для начала эта команда становится довольно длинной, когда включаются все годы. Плюс это многопользовательская и медленная работа. Есть ли более простой/быстрый код для этого?

+3

'Reduce (пересекаются, расщепленный (ДФ $ код, DF $ год)) ' –

ответ

2

Как еще одна идея, вы могли бы работать на структуре вхождений в год, что может быть удобным и более эффективным по дороге вместо многих попарных пересечений:

lvls = list(y = unique(df$year), c = levels(df$code)) 

library(Matrix) 
tab = sparseMatrix(i = match(df$year, lvls$y), 
        j = match(df$code, lvls$c), 
        x = TRUE, 
        dimnames = lvls) 

tab 
#3 x 3 sparse Matrix of class "lgCMatrix" 
#  c 
#y  a b c 
# 2009 | | . 
# 2010 . | . 
# 2011 . | | 

И тогда:

colSums(tab) == nrow(tab) 
# a  b  c 
#FALSE TRUE FALSE 

или, в данном случае лучше:

colnames(tab)[diff([email protected]) == nrow(tab)] 
#[1] "b" 

"ДФ" является:

df = structure(list(year = c(2009L, 2009L, 2009L, 2010L, 2010L, 2011L, 
2011L, 2011L), code = structure(c(1L, 1L, 2L, 2L, 2L, 2L, 3L, 
3L), .Label = c("a", "b", "c"), class = "factor")), .Names = c("year", 
"code"), class = "data.frame", row.names = c(NA, -8L)) 
0

Использование tidyverse функции и considerng dft1 в качестве входных данных, вы можете попробовать:

dft1 %>% 
    unique() %>% 
    group_by(code) %>% 
    filter(n_distinct(year) == length(unique(dft1$year))) 

, который дает:

year code 
    <int> <chr> 
1 2009  b 
2 2010  b 
3 2011  b 
Смежные вопросы