R: how to reorder the legend key in the ggplot2 graph line to match the final values ​​in each series?

I draw line charts showing price changes over time for several instruments using ggplot2. I managed to get some lines on the plot and add values ​​showing the most recent price change. What I want to do (and have not yet reached) is to reorder the legend key so that the price series that has risen the most is at the top of the legend, and then the price series key that has risen to second place and and etc.

In the figure below, the legend shows the key in alphabetical order. What I would like to do is show the legend key entries in the order DDD, AAA, CCC, then BBB, which is the order of execution on the most recent date. How can i do this?

ggplo2 chart showing legend order

The following is the minimum code.

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)
+5
source share
2 answers

Try the following:

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

I melted a complete dataset to save multiple lines for building code. The key, as usual, is to make sure that the variable is an ordered factor.

To fix the problem that arose in the comments, you can pass on any shortcuts that you like in the legend itself, until you get the correct order:

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

. 0.9.2 opts theme, :

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

, . , , - . , , , ( max min min max). .

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)
0

All Articles