2012-03-11 34 views
5

Un par de semanas atrás que utiliza ggplot2 para crear una parcela facetas donde las facetas fueron ordenados por el último valor de la trama de datos. No tuve mayores problemas hasta que llegó el momento de reordenar, ya que no he asimilado todas las complicaciones de órdenes, factores y niveles. Aún así, después de una o dos horas (o tres) de referirme a las publicaciones de SO lo conseguí funcionando.R: ordenar las facetas de valor en lugar de por orden alfabético en una parcela ggplot2

Cuando volví al script de hoy, ya no estaba "funcionando", ya que ahora está ordenando las facetas por orden alfabético en lugar de por el valor final del marco de datos. (Creo que originalmente "fijo", mientras que el problema de jugar un poco en la consola R y en realidad no añadir la solución a la secuencia de comandos.) En lugar de pasar un par de horas en esta noche voy a tirarme a la merced de SO.

P. ¿Cómo puedo ordenar las facetas por un valor especificado en lugar de por el orden alfabético de los nombres de cada faceta? Tenga en cuenta que el siguiente código es solo un ejemplo; los datos reales tienen varias docenas de artículos.

código Editado abajo para reflejar entrada adicional de @joran; las facetas ahora están ordenadas y llenadas apropiadamente. Misión exitosa.

# Version 3 
require(ggplot2) ## NB This script assumes you have ggplot2 v0.90 
require(scales) 
require(plyr) 
require(lubridate) 
require(reshape) 

set.seed(12345) 
monthsback <- 15 
date <- as.Date(paste(year(now()),month(now()),"1",sep="-")) - months(monthsback) 
myitems <- data.frame(mydate=seq(as.Date(date), by="month", length.out=monthsback), 
         aaa = runif(monthsback, min = 600, max = 800), 
         bbb = runif(monthsback, min = 100, max = 200), 
         ccc = runif(monthsback, min = 1400, max = 2000), 
         ddd = runif(monthsback, min = 50, max = 120)) 

myitems <- melt(myitems, id = c('mydate')) 

change_from_start <- function(x) { 
    (x - x[1])/x[1] 
} 

myitems <- ddply(myitems, .(variable), transform, value = change_from_start(value)) 
myitems$mydate <- as.Date(myitems$mydate, format = "%Y-%m-%d") 
myvals <- myitems[myitems$mydate == myitems$mydate[nrow(myitems)],] # get values on which to sort facets 
myvals <- within(myvals, variable <- factor(variable, as.character(myvals[order(myvals$value, decreasing = T),]$variable),ordered = TRUE)) 
myitems <- within(myitems, variable <- factor(variable, as.character(myvals[order(myvals$value, decreasing = T),]$variable),ordered = TRUE)) 
print(levels(myitems$variable)) # check to see if ordering succeeded 
myitems$fill <- ifelse(myitems$variable == "ddd", "blue", "darkgreen") 

    p <- ggplot(myitems, aes(y = value, x = mydate, group = variable)) + 
     geom_rect(aes(xmin = as.Date(myitems$mydate[1]), xmax = Inf, fill = fill), ymin = -Inf, ymax = Inf) + 
     scale_fill_manual(values = c("blue", "darkgreen")) + 
     geom_line(colour = "black") + 
     geom_text(data = myvals, aes(x = as.Date(myitems$mydate[1]) + 250, y = 0.2, label = sprintf("%1.1f%%", value * 100))) + 
     facet_wrap(~ variable, ncol = 2) + 
     geom_hline(yintercept = 0, size = 0.6, linetype = "dotdash") + 
     scale_y_continuous(label = percent_format()) + 
     scale_x_date(expand = c(0,0), labels = date_format("%Y-%m"), breaks = date_breaks("year")) + 
     xlab(NULL) + 
     ylab(NULL) + 
     opts(legend.position = "none") + 
     opts(panel.grid.minor = theme_blank()) + 
     opts() 

print(p) 

Image showing that facets are now sorted properly but that the fill is no longer working

Respuesta

3

Usted tiene dos problemas:

  1. La línea que convierte myitems$variable a un factor debe especificar ordered = TRUE, para asegurar que va a ser un factor ordenada.

  2. Su llamada geom_text utiliza una trama de datos separada cuya correspondiente variable no es un factor (u ordenado) por lo que está pisando fuerte en la naturaleza ordenada de la de myitems.

los convierten tanto u ordenados factores, y que debe estar bien.

+0

Gracias, creo que veo. Tendré otra oportunidad mañana. – SlowLearner

+0

Agregué 'ordered = TRUE' al marco de datos myvals y al marco de datos myitems y ahora ambos ordenan como uno esperaría. Sin embargo ... Ahora estoy descubriendo que el relleno está roto, presumiblemente porque está llenando la columna de relleno y no los niveles de factores ordenados. Es decir, si "ddd" se encuentra en la segunda faceta de la segunda faceta debe ser de color azul y el verde de descanso, pero siempre es la cuarta faceta - la ubicación original de "DDD" - que se llena de color azul. He intentado con pedir que la columna de relleno resuelva esto pero no puedo hacer que funcione. ¿Debería ser esta una pregunta separada? – SlowLearner

+1

@SlowLearner Cambie 'fill = myitems $ fill' a' fill = fill'.Es una diferencia sutil, pero de lo contrario su variable de relleno no está vinculada a las otras variables en el marco de datos, ya que acaba de pasar un vector de pie. – joran

0

de faceta están clasificadas en el mismo orden como variables en data.frame fuente.
Así como un truco básico que sólo puede ordenar nombre de las variables al crear el hoja.de.datos:

myitems <- data.frame(mydate=seq(as.Date(date), by="month", length.out=monthsback), 
     'ccc' = runif(monthsback, min = 1400, max = 2000), 
     'aaa' = runif(monthsback, min = 600, max = 800), 
     'ddd' = runif(monthsback, min = 50, max = 120), 
     'bbb' = runif(monthsback, min = 100, max = 200) 
     ) 

Si necesita reordenar al final del proceso, después arreglan() podría ser la mejor solución.

+0

Gracias por esta sugerencia. No lo dejé claro en mi pregunta, pero los datos reales tienen varias docenas de elementos y los valores por los que se deben ordenar las facetas cambiarán con frecuencia, por lo que el reordenamiento manual sería bastante engorroso. – SlowLearner

Cuestiones relacionadas