2012-04-09 12 views
5

Estoy trazando gráficos de líneas que muestran el cambio en el precio a lo largo del tiempo para múltiples instrumentos, usando ggplot2. Logré obtener varias líneas en la trama y agregué valores que mostraban el cambio más reciente en el precio. Lo que quiero hacer (y aún no lo he logrado) es reordenar la clave de leyenda para que la serie de precios que ha subido más esté en la parte superior de la leyenda, seguida de la clave de la serie de precios que se elevó en segundo lugar y pronto.R: ¿cómo reordenar la clave de leyenda en el diagrama de línea ggplot2 para que coincida con los valores finales en cada serie?

En el siguiente diagrama, la leyenda muestra la clave en orden alfabético. Lo que me gustaría hacer es mostrar las entradas de la clave de leyenda en el orden DDD, AAA, CCC y BBB, que es el orden de ejecución a la fecha más reciente. ¿Cómo puedo hacer esto?

código

ggplo2 chart showing legend order

Mínimo-ish sigue.

require(ggplot2) 
require(scales) 
require(gridExtra) 
require(lubridate) 
require(reshape) 

# create fake price data 
set.seed(123) 
monthsback <- 15 
date <- as.Date(paste(year(now()), month(now()),"1", sep="-")) - months(monthsback) 
mydf <- 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)) 

# function to calculate change 
change_from_start <- function(x) { 
    (x - x[1])/x[1] 
} 

# for appropriate columns (i.e. not date), replace fake price data with change in price 
mydf[, 2:5] <- lapply(mydf[, 2:5], function(myparam){change_from_start(myparam)}) 

# get most recent values and reshape 
myvals <- mydf[mydf$mydate == mydf$mydate[nrow(mydf)],] 
myvals <- melt(myvals, id = c('mydate')) 

# plot multiple lines 
p <- ggplot(data = mydf) + 
    geom_line(aes(x = mydate, y = aaa, colour = "AAA"), size = 1) + 
    geom_line(aes(x = mydate, y = bbb, colour = "BBB"), size = 1) + 
    geom_line(aes(x = mydate, y = ccc, colour = "CCC"), size = 1) + 
    geom_line(aes(x = mydate, y = ddd, colour = "DDD"), size = 1) + 
    scale_colour_manual("", values = c("AAA" = "red", "BBB" = "black", "CCC" = "blue", "DDD" = "green")) + 
    scale_y_continuous(label = percent_format()) + 
    geom_text(data = myvals, aes(x = mydate + 30, y = value, label = sprintf("%+1.1f%%", myvals$value * 100)), size = 4, colour = "grey50") + 
    opts(axis.title.y = theme_blank()) + 
    opts() 

# and output 
print(p) 

Respuesta

9

Prueba esto:

mydf <- melt(mydf,id.var = 1) 
mydf$variable <- factor(mydf$variable,levels = rev(myvals$variable[order(myvals$value)]),ordered = TRUE) 

# plot multiple lines 
p <- ggplot(data = mydf) + 
    geom_line(aes(x = mydate,y = value,colour = variable,group = variable),size = 1) + 
    scale_colour_manual("", values = c("aaa" = "red", "bbb" = "black", "ccc" = "blue", "ddd" = "green")) + 
    scale_y_continuous(label = percent_format()) + 
    geom_text(data = myvals, aes(x = mydate + 30, y = value, label = sprintf("%+1.1f%%", myvals$value * 100)), 
       size = 4, colour = "grey50") + 
    opts(axis.title.y = theme_blank()) + 
    opts() 

# and output 
print(p) 

enter image description here

que funde su conjunto completo de datos para ahorrar varias líneas de código para el trazado. La clave, como de costumbre, es asegurarse de que la variable sea un factor ordenado.

Para abordar el problema que surgió en los comentarios, puede pasar cualquier cosa etiquetas te gusta a aparecer en la propia leyenda, siempre y cuando se obtiene el orden correcto:

ggplot(data = mydf) + 
    geom_line(aes(x = mydate,y = value,colour = variable,group = variable),size = 1) + 
    scale_colour_manual("", values = c("aaa" = "red", "bbb" = "black", "ccc" = "blue", "ddd" = "green"),labels = c('Company D','Company A','Company C','Company B')) + 
    scale_y_continuous(label = percent_format()) + 
    geom_text(data = myvals, aes(x = mydate + 30, y = value, label = sprintf("%+1.1f%%", myvals$value * 100)), 
       size = 4, colour = "grey50") + 
    opts(axis.title.y = theme_blank()) + 
    opts() 

enter image description here

Nota: Desde la versión 0.9.2 opts ha sido replaced por theme, por ejemplo:

+ theme(axis.title.y = element_blank()) 
+3

Perfecto! Tenga en cuenta que 'factor ordenado 'es innecesario. El orden del nivel es importante, pero a ggplot2 no le importa si el factor está ordenado o no. – kohske

+0

¡Es bueno saberlo, @kohske, gracias! Supongo que soy demasiado paranoico sobre el código de otras personas que decide sobre su propio pedido si el factor no está ordenado. – joran

+0

Gracias a joran por esto, estaba evitando un derretimiento para el marco de datos principal, pero no tiene ninguna consecuencia real y, como usted señala, ahorra un montón de repeticiones. Supongo que sería posible definir la parte 'values ​​= c (" aaa "=" red ")' por separado usando una lista para no tener que ahondar en la parte ggplot del código cada vez que quiero hacer cambios a los elementos que quiero trazar ...? Gracias también a kohske por su entrada. – SlowLearner

0

Creo que hay una manera más fácil. Una vez que funde el marco de datos, pídalo por valor de fecha y use los valores de la última fecha para crear la leyenda. Dado que ordenó por valor, la leyenda mostrará las líneas en el orden correspondiente a la forma en que haya ordenado el valor (máximo a mínimo o mínimo a máximo). Código a continuación.

require(ggplot2) 
require(scales) 
require(gridExtra) 
require(lubridate) 
require(reshape) 

# create fake price data 
set.seed(123) 
monthsback <- 15 
date <- as.Date(paste(year(now()), month(now()),"1", sep="-")) - months(monthsback) 
mydf <- 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)) 

# function to calculate change 
change_from_start <- function(x) { 
    (x - x[1])/x[1] 
} 

# for appropriate columns (i.e. not date), replace fake price data with change in price 
mydf[, 2:5] <- lapply(mydf[, 2:5], function(myparam){change_from_start(myparam)}) 

mydf <- melt(mydf, id.var=1) 

#Order by date and value. Decreasing since want to order greatest to least 
mydf <- mydf[order(mydf$mydate, mydf$value, decreasing = TRUE),] 

#Create legend breaks and labels 
legend_length <- length(unique(mydf$variable)) 
legend_breaks <- mydf$variable[1:legend_length] 

#Pass order through scale_colour_discrete 
ggplot(data=mydf) + geom_line(aes(x = mydate,y = value,colour = variable,group = variable),size = 1) + scale_colour_discrete(breaks=legend_breaks) 
Cuestiones relacionadas