2016-09-13 1 views
2

Я изучаю ИБМД фильм набор данных в kaggle с R.Group колонкой и сортировать по другой колонке в R

Вот минимальный набор данных репродукция:

> movies <- data.frame(movie = as.factor(c("Movie 1", "Movie 2", "Movie 3", "Movie 4")), director = as.factor(c("Dir 1", "Dir 2", "Dir 1", "Dir 3")), director_rating = c(1000, 2000, 1000, 3000)) 

> movies 
    movie director director_rating 
1 Movie 1 Dir 1   1000 
2 Movie 2 Dir 2   2000 
3 Movie 3 Dir 1   1000 
4 Movie 4 Dir 3   3000 

Обратите внимание, что каждая строка, которая имеет тот же директор имеет такое же значение рейтинга для директора.

Я хочу перечислить директоров, отсортированных по рейтингу, и по одному ряду за директора. Следующий код работает:

> library(dplyr) 
> movies %>% 
    group_by(director) %>% 
    summarize(director_rating = mean(director_rating)) %>% 
    arrange(desc(director_rating)) 

    # A tibble: 3 x 2 
    director director_rating 
    <fctr>   <dbl> 
1 Dir 3   3000 
2 Dir 2   2000 
3 Dir 1   1000 

Но, кажется расточительной для вычисления среднего значения, когда я знаю, что все рейтинги для одного директоров идентичны. Что является более идиоматическим/эффективным способом сделать это в R?

+1

Просто используйте 'first' вместо' означает, 'вернуть первый рейтинг? – aichao

+0

@aichao - да, это работает - я забыл о том, что «первый» доступен в R :-) – Anand

+0

«каждая строка, имеющая того же директора, имеет такое же значение рейтинга для директора» - Fyi, это плохой способ для структурирования данных. У вас должны быть отдельные таблицы «фильмы» и «директора» с соответствующими атрибутами. Возможно, вам захочется прочитать мысли Хэдли о «аккуратных» данных: https://www.jstatsoft.org/article/view/v059i10/ – Frank

ответ

3

На самом деле нет необходимости группировать и суммировать, так как вы просто ищете отдельные/уникальные записи. Опция dplyr поэтому:

select(movies, -movie) %>% 
    distinct() %>% 
    arrange(desc(director_rating)) 
# director director_rating 
#1 Dir 3   3000 
#2 Dir 2   2000 
#3 Dir 1   1000 

Или в случае, если вы хотите сохранить другие столбцы:

distinct(movies, director, .keep_all = TRUE) %>% # for dplyr >= 0.5.0 
    arrange(desc(director_rating)) 
# movie director director_rating 
#1 Movie 4 Dir 3   3000 
#2 Movie 2 Dir 2   2000 
#3 Movie 1 Dir 1   1000 
+2

В dplyr 0.5.0 ваш второй способ не работает. Значение по умолчанию в 'distinct' означает падение столбцов, отличных от' director'. Gotta do 'different (фильмы, режиссер, .keep_all = TRUE)%>% arr (desc (director_rating))' Может быть, моя версия отстает от времени или чего-то еще ... – Frank

+2

@Frank благодарит за это. Я еще не обновил до 0,5 –

2

Мы можем использовать data.table

library(data.table) 
setDT(movies)[, .(director_rating = director_rating[1]), director][order(-director_rating)] 
# director director_rating 
#1: Dir 3   3000 
#2: Dir 2   2000 
#3: Dir 1   1000 

Или с setorder/unique где unique из data.table также имеют возможность by.

unique(setorder(setDT(movies), -director_rating), by = "director") 
+0

Да, это работает - спасибо. Хотелось бы также знать, как это сделать идиоматически по пути dplyr. – Anand

+1

@Anand После шага 'group_by' используйте' summaryize (director_rating = first (director_rating)) ' – akrun

3

Вот base R вариант:

unique(movies[,2:3])[order(-unique(movies[,2:3])[,2]),] 
# director director_rating 
#4 Dir 3   3000 
#2 Dir 2   2000 
#1 Dir 1   1000 
+2

Всегда полезно показывать альтернативу базы R. В этом случае вы можете рассмотреть возможность хранения уникальных (movies [, 2: 3]) 'в новом объекте, поэтому вам не нужно его дважды вычислять (в случае больших наборов данных) –