Подмножество фрейма данных с топ-n строк для каждой группы и упорядочены по переменной - PullRequest
8 голосов
/ 20 мая 2011

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

    d1 <- data.frame(Gender = c("M", "M", "F", "F", "M", "M", "F", 
  "F"), Age = c(15, 38, 17, 35, 26, 24, 20, 26))

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

Gender  Age  
F   35  
F   26  
M   38  
M   26  

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

Ответы [ 6 ]

13 голосов
/ 20 мая 2011

Одно решение с использованием ddply() из plyr

require(plyr)
ddply(d1, "Gender", function(x) head(x[order(x$Age, decreasing = TRUE) , ], 2))
6 голосов
/ 20 мая 2011

С пакетом data.table

require(data.table)
dt1<-data.table(d1)# to speedup you can add setkey(dt1,Gender)
dt1[,.SD[order(Age,decreasing=TRUE)[1:2]],by=Gender]
1 голос
/ 20 мая 2011

Я уверен, что есть лучший ответ, но вот один из способов:

require(plyr)
ddply(d1, c("Gender", "-Age"))[c(1:2, 5:6),-1]

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

new.d1=ddply(d1, c("Gender", "-Age"))[,-1]
pos=match('M',new.d1$Gender) # pos wil show index of first entry of M
new.d1[c(1:2,pos:(pos+1)),]
0 голосов
/ 30 марта 2019
d1 = d1[order(d1$Gender, -d1$Age),]  
d1 = d1[ave(d1$Age, d1$Gender, FUN = seq_along) <= 2, ]

Была похожая проблема, и этот метод оказался очень быстрым при использовании на data.frame с 1,5 миллионами записей

0 голосов
/ 05 января 2017

У меня есть предложение, если вам нужны, например, первые 2 женщины и первые 3 мужчины:

library(plyr)
m<-d1[order(d1$Age, decreasing = TRUE) , ] 
h<-mapply(function(x,y) head(x,y), split(m$Age,m$Gender),y=c(2,3)) 
ldply (h, data.frame)

Вам просто нужно изменить имена окончательного фрейма данных.

0 голосов
/ 25 сентября 2011

Это даже проще, если вы просто хотите выполнить сортировку:

d1 <- transform(d1[order(d1$Age, decreasing=TRUE), ], Gender=as.factor(Gender))

Вы можете позвонить:

require(plyr)
d1 <- ddply(d1, .(Gender), head, n=2)

для поднабора двух верхних в каждой подгруппе по полу.

...