Seleccione un valor basado en un mayor valor de otra columna
Pregunta
No entiendo por qué no puedo encontrar una solución para esto, ya que siento que esta es una pregunta bastante básica.Necesidad de pedir ayuda, entonces.Quiero reorganizar airquality conjunto de datos por mes con temperatura máxima de valor para cada mes.Además, quiero encontrar el día que corresponda para cada mensuales de temperatura máxima.¿Cuál es el más perezoso (código-wise) manera de hacer esto?
He intentado 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)
Yo después de algo como esto:
month day temp
5 7 89
...
Solución
Hubo una gran discusión, mientras que es perezoso es bueno o no.Anwyay, esto es corto y natural para escribir y leer (y es rápido para obtener datos grandes, por lo que no necesita cambiarlo o optimizarlo 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 desea la fila de ella 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 ata el 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
Otros consejos
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, incluso más sencillo
require(reshape2)
require(plyr)
names(airquality) <- tolower(names(airquality))
ddply(airquality, .(month), subset,
subset = temp == max(temp), select = c(month, day, temp) )
¿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.
O si desea utilizar el data.table
paquete (por ejemplo, si la velocidad es un problema y el conjunto de datos es grande o si usted 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
significa, echa un vistazo aquí: ASÍ