2015-07-28 4 views
4

Допустим, у меня есть data.table какФильтр data.table по количеству группы

sample<-data.table(id=c(1,1,2,2,3,3,3,4,4), 
        name=c("apple","apple","orange","orange", 
          "pear","pear","pear","banana","banana"), 
       atr=c("pretty","ugly","bruised","delicious", 
        "pear-shaped","bruised","infested", 
        "too-ripe","perfect"), 
       N=c(10,9,15,4,5,7,7,4,12)) 

Я хочу вернуться в основном unique(sample[,list(id, name)]) кроме того, что я также хочу atr столбец значения с наибольшим N. В тех случаях, когда есть связь для самого высокого N, тогда мне все равно, какая из двух выбрана, но я хочу, чтобы только один был выбран.

Это почти работает merge(sample[,list(N=max(N)),by=list(id,name1)], sample,by=c("id","name1","N")), но поскольку груша имеет два значения, которые связывают для максимального, это возвращает две груши. Кроме того, что он не дает ожидаемого результата, я также предполагаю/надеюсь, что есть способ сделать это, не связанный с объединением.

ответ

3

Я бы просто использование order:

> unique(sample[order(-N), .(id, name, atr)], by = c("id", "name")) 
    id name  atr 
1: 2 orange bruised 
2: 4 banana perfect 
3: 1 apple pretty 
4: 3 pear bruised 

Если вы хотите m aintain общей сортировки, просто используйте вместо этого order(id, name, -N).

Вы также можете разбить это на две линии:

setorder(sample, -N) #done by reference, as with all set* functions in data.table 
unique(sample[ , .(id, name, atr)], by = c("id", "name")) 

или, возможно, лучше, в зависимости от вашей конечной цели:

setkey(setorder(sample, -N), id, name) 
unique(sample[ , .(id, name, atr)]) 

(примечание: порядок имеет решающее значение в этой последней, как использование setorder первый перезаписывает ключи до NULL)

+0

Я не знал, что уникальная принятая 'by'. Я также был удивлен, что это было быстрее, чем подход Ричарда. Конечно, это была разница между .001 и .005 секунд (для моего фактического набора данных), поэтому он не имеет никакого реального влияния на мир. –

+0

@DeanMacGregor да, аргумент 'by' особенно полезен, если: a) вы хотите, чтобы ваш оригинальный ключ' data.table' был неповрежденным при использовании 'unique' и b), если вы хотите пойти' unique' на некоторые, но не все ключи вашей 'data.table'. – MichaelChirico

+0

Делает мне желание по аргументу в голове и хвосте –

4

Вы можете использовать atr[N == max(N)][1] вернуть только первый в случае равенства, как это -

library(data.table) 

sample[, .(atr = atr[N == max(N)][1]), by = .(id, name)] 
# id name  atr 
# 1: 1 apple pretty 
# 2: 2 orange bruised 
# 3: 3 pear bruised 
# 4: 4 banana perfect 

Примечание: Как Франк указывает atr[N == max(N)][1] также просто atr[which.max(N)]

+0

Это только для справки, так как я должен был сделать что-то подобное недавно, но если вы хотите обрабатывать случаи с галстуком в более сложном w ay, вы можете сделать что-то вроде 'sample [, {x <-atr [N == max (N)]; if (length (x)> 1) x else * случай действия tie *}, by =. (id, name)] ' – MichaelChirico

+2

Вы можете получить первый матч с' which.max', правильно? 'atr = atr [which.max (N)]' – Frank

+1

@Frank - Да, точно. Это функция, которую я не мог вспомнить прошлой ночью! Cheers –

Смежные вопросы