2012-05-22 11 views
6

No entiendo por qué no puedo encontrar una solución para esto, ya que siento que esta es una pregunta bastante básica. Necesito pedir ayuda, entonces. Deseo reorganizar el conjunto de datos de calidad aérea por mes con el valor máximo de temperatura para cada mes. Además, quiero encontrar el día correspondiente para cada temperatura máxima mensual. ¿Cuál es la forma más lenta (en código) de hacer esto?Seleccione un valor para basado en un valor más alto en otra columna

He tratado siguiendo sin éxito:

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) 

Soy después de algo como esto:

month day temp 
5  7 89 
... 

Respuesta

5

Hubo bastante discusión hace un tiempo acerca de si ser perezoso es bueno o no. Anwyay, esto es corto y natural para escribir y leer (y es rápido de datos de gran tamaño por lo que no es necesario cambiar u optimizar más tarde):

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 es el subconjunto de los datos para cada grupo, y solo quieres la fila con la temperatura más grande, iiuc. Si necesita el número de fila, entonces se puede agregar.

O para obtener todas las filas donde se amarra al máximo:

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

¡Gracias chicos! No he usado el paquete data.table anteriormente, así que es casi una vez. "Respuesta aceptada" porque esta fue la más completa (y ligeramente más corta que la de Chritoph_J). Sin embargo, todos ustedes lo habrían merecido (+1 para todos). – Mikko

+0

Me pregunto si hay una solución más concisa en cualquier idioma. Supongo que no. –

2

¿qué tal 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) 

Como puede ver, la temperatura máxima para el mes ocurre en más de un día. Si desea un comportamiento diferente, la función es lo suficientemente fácil de ajustar.

2

O si desea utilizar el paquete data.table (por ejemplo, si la velocidad es un problema y el conjunto de datos es grande o si lo prefiere la sintaxis):

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

Si usted quiere saber lo que el .SD son las siglas, échele un vistazo aquí: SO

+0

Creo que me ganaste en eso :) –

+0

En lo que respecta al tiempo, sí, en dos segundos (tiempo para celebrar ;-) Pero tu truco 'which.max' está bien ... ¡así que +1 para eso! –

3

Otro enfoque 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) 

Da

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 

O, aún más simple

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