2012-05-22 11 views
6

Non capisco perché non riesco a trovare una soluzione per questo, poiché ritengo che questa sia una domanda piuttosto semplice. Hai bisogno di chiedere aiuto, allora. Voglio riorganizzare il set di dati di airquality per mese con il massimo valore di temperatura per ogni mese. Inoltre voglio trovare il giorno corrispondente per ogni temperatura massima mensile. Qual è il modo più pigro (in termini di codice) per farlo?Selezionare un valore basato su un valore più alto in un'altra colonna

ho cercato segue senza un successo:

require(reshape2) 
names(airquality) <- tolower(names(airquality)) 
mm <- melt(airquality, id.vars = c("month", "day"), meas = c("temp")) 

dcast(mm, month + day ~ variable, max) 
aggregate(formula = temp ~ month + day, data = airquality, FUN = max) 

Sono alla ricerca di qualcosa di simile:

month day temp 
5  7 89 
... 

risposta

5

C'è stata una discussione abbastanza indietro sul fatto se essere pigri è buono o no. Anwyay, questo è breve e naturale per scrivere e leggere (ed è veloce per i dati di grandi dimensioni in modo che non c'è bisogno di modificare o ottimizzare in un secondo momento):

require(data.table) 
DT=as.data.table(airquality) 

DT[,.SD[which.max(Temp)],by=Month] 

    Month Ozone Solar.R Wind Temp Day 
[1,]  5 45  252 14.9 81 29 
[2,]  6 NA  259 10.9 93 11 
[3,]  7 97  267 6.3 92 8 
[4,]  8 76  203 9.7 97 28 
[5,]  9 73  183 2.8 93 3 

.SD è il sottoinsieme di dati per ogni gruppo, e vuoi solo la riga da essa con il Temp più grande, iiuc. Se è necessario il numero di riga, è possibile aggiungerlo.

O per ottenere tutte le righe in cui il massimo è legato:

DT[,.SD[Temp==max(Temp)],by=Month] 

    Month Ozone Solar.R Wind Temp Day 
[1,]  5 45  252 14.9 81 29 
[2,]  6 NA  259 10.9 93 11 
[3,]  7 97  267 6.3 92 8 
[4,]  7 97  272 5.7 92 9 
[5,]  8 76  203 9.7 97 28 
[6,]  9 73  183 2.8 93 3 
[7,]  9 91  189 4.6 93 4 
+0

Grazie ragazzi! Non ho usato il pacchetto data.table in precedenza, quindi è un po 'di tempo. "Risposta accettata" perché questa era la più completa (e leggermente più corta di quella di Chritoph_J). Tutti voi lo avreste meritato, però (+1 per tutti). – Mikko

+0

Mi chiedo se esiste una soluzione più concisa in qualsiasi lingua. Sto indovinando no. –

2

come circa con plyr?

max.func <- function(df) { 
    max.temp <- max(df$temp) 

    return(data.frame(day = df$Day[df$Temp==max.temp], 
        temp = max.temp)) 
} 

ddply(airquality, .(Month), max.func) 

Come si può vedere, la temperatura massima del mese si verifica per più di un giorno. Se vuoi un comportamento diverso, la funzione è abbastanza facile da regolare.

2

Oppure, se si vuole utilizzare il pacchetto data.table (per esempio, se la velocità è un problema e il set di dati è di grandi dimensioni o se si preferisce la sintassi):

library(data.table) 
DT <- data.table(airquality) 
DT[, list(maxTemp=max(Temp), dayMaxTemp=.SD[max(Temp)==Temp, Day]), by="Month"] 

Se volete sapere qual è il .SD sta per, dai un'occhiata qui: SO

+0

Penso che tu mi abbia battuto su quello :) –

+0

In termini di tempo, sì, di due secondi (tempo per festeggiare ;-) Ma il tuo trucco "which.max' è pulito ... quindi +1 per quello! –

3

Un altro approccio con plyr

require(reshape2) 
names(airquality) <- tolower(names(airquality)) 
mm <- melt(airquality, id.vars = c("month", "day"), meas = c("temp"), value.name = 'temp') 

library(plyr) 

ddply(mm, .(month), subset, subset = temp == max(temp), select = -variable) 

month day temp 
1  5 29 81 
2  6 11 93 
3  7 8 92 
4  7 9 92 
5  8 28 97 
6  9 3 93 
7  9 4 93 

Oppure, ancora più semplice

require(reshape2) 
require(plyr) 
names(airquality) <- tolower(names(airquality)) 
ddply(airquality, .(month), subset, 
    subset = temp == max(temp), select = c(month, day, temp)) 
Problemi correlati