2012-04-09 2 views
5

Ich zeichne Liniendiagramme, die die Veränderung des Preises im Laufe der Zeit für mehrere Instrumente zeigen, mit ggplot2. Es ist mir gelungen, mehrere Linien auf der Handlung zu bekommen und Werte hinzuzufügen, die die letzte Preisänderung zeigen. Was ich tun möchte (und noch nicht erreicht habe), ist, den Legendenschlüssel neu anzuordnen, so dass die am weitesten gestiegene Preisreihe an der Spitze der Legende steht, gefolgt vom Schlüssel der Preisreihe, die am zweithäufigsten gestiegen ist bald.R: Wie wird der Legendenschlüssel im ggplot2-Liniendiagramm neu angeordnet, um den endgültigen Werten in jeder Serie zu entsprechen?

In der folgenden Abbildung zeigt die Legende den Schlüssel in alphabetischer Reihenfolge. Was ich möchte, ist, die Legende Schlüsseleinträge in der Reihenfolge DDD, AAA, CCC und BBB, die die Reihenfolge der Leistung ab dem letzten Datum ist. Wie kann ich das machen?

ggplo2 chart showing legend order

Minimal-ish-Code folgt.

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) 

Antwort

9

Try this:

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

ich Ihren vollständigen Datensatz geschmolzen mehrere Zeilen Code zum Plotten zu speichern. Der Schlüssel ist, wie üblich, sicherzustellen, dass die Variable ein geordneter Faktor ist. korrekte

Um das Problem zu adressieren, die in den Kommentaren entstanden ist, können Sie, was Etiketten Sie passieren in der Legende erscheinen mag sich, solange Sie den Auftrag erhalten:

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

Hinweis: Seit der Version 0.9.2 opts hat replaced durch theme, zB:

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

Perfekt! Beachten Sie, dass "geordneter Faktor" nicht erforderlich ist. Reihenfolge des Levels ist wichtig, aber ggplot2 kümmert sich nicht darum, ob der Faktor geordnet ist oder nicht. – kohske

+0

Gut zu wissen, @kohske, danke! Ich denke, ich bin über den Code anderer Leute zu paranoid, der über ihre eigene Ordnung entscheidet, wenn der Faktor nicht bestellt wird. – joran

+0

Dank joran dafür - ich habe eine Schmelze für den Hauptdatenrahmen vermieden, aber es hat keine wirkliche Konsequenz und wie Sie darauf hinweisen, spart eine Menge Standard. Ich denke, es wäre möglich, den 'values ​​= c (" aaa "=" red ")' -Teil separat unter Verwendung einer Liste zu definieren, so dass ich den ggplot-Teil des Codes nicht jedes Mal neu eingeben muss, wenn ich etwas machen möchte Änderungen an den Elementen, die ich zeichnen möchte ...? Danke auch an kohske für die Eingabe. – SlowLearner

0

Ich denke, es gibt einen einfacheren Weg. Nachdem Sie den Datenrahmen geschmolzen haben, sortieren Sie ihn nach Datum und verwenden Sie die Werte für das letzte Datum, um die Legende zu erstellen. Da Sie nach Wert sortiert haben, zeigt die Legende die Zeilen in der Reihenfolge an, in der Sie den Wert angegeben haben (max bis min oder min bis max). Code unten.

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)