2012-03-11 21 views
5

Un paio di settimane fa ho utilizzato ggplot2 per creare un grafico sfaccettato in cui le faccette erano ordinate in base all'ultimo valore nel frame di dati. Non ho avuto grossi problemi fino al momento del riordino, in quanto non ho davvero assimilato tutte le complicazioni di ordini, fattori e livelli. Eppure, dopo un'ora o due (o tre) di riferimento ai post SO, l'ho fatto funzionare.R: ordinare gli sfaccettature in base al valore anziché in ordine alfabetico in un grafico ggplot2

Quando sono tornato alla sceneggiatura oggi non stava più "lavorando" in quanto ora sta ordinando le sfaccettature in ordine alfabetico piuttosto che in base al valore finale del frame dati. (Penso che originariamente "aggiustai" il problema mentre facevo casino alla console R e non ho aggiunto la soluzione alla sceneggiatura.) Piuttosto che passare un altro paio di ore su questo stasera, mi metto in balia della misericordia di SO.

D. Come posso ordinare le faccette per un valore specificato anziché per l'ordine alfabetico dei nomi di ogni faccetta? Si prega di notare che il seguente codice è solo un esempio; i dati reali hanno diverse dozzine di elementi.

Codice modificato sotto per riflettere l'input aggiuntivo da @joran; le sfaccettature sono ora ordinate e riempite in modo appropriato. Missione di successo.

# 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

risposta

3

Si hanno due problemi:

  1. La linea che converte myitems$variable ad un fattore dovrebbe specificare ordered = TRUE, per assicurare che sarà un fattore ordinato.

  2. tuo geom_text chiamata utilizza un frame di dati separato cui corrispondente variabile non è un fattore (o ordinato) quindi è stomping sulla natura ordinata di quella di myitems.

convertirli sia o ordinati fattori, e si dovrebbe andare bene.

+0

Grazie, penso di vedere. Ne avrò un altro domani. – SlowLearner

+0

Ho aggiunto 'ordered = TRUE' al frame di dati myvals e il frame dei dati myitems e ora entrambi ordinano come ci si aspetterebbe. Tuttavia ... Ora sto scoprendo che il riempimento è rotto, presumibilmente perché si sta riempiendo la colonna di riempimento e non i livelli del fattore ordinato. Cioè, se "ddd" è nella seconda faccetta, la seconda faccetta dovrebbe essere colorata in blu e la restante in verde, ma è sempre la quarta faccetta - la posizione originale di "ddd" - che è riempita di blu. Ho provato a provare a ordinare la colonna di riempimento per risolvere questo problema ma non riesco a farlo funzionare. Questa dovrebbe essere una domanda a parte? – SlowLearner

+1

@SlowLearner Modifica 'fill = myitems $ fill' su' fill = fill'.È una differenza sottile, ma in caso contrario la variabile di riempimento non è legata alle altre variabili nel frame di dati, dal momento che l'hai appena passato a un vettore indipendente. – joran

0

sfaccettatura sono ordinate nello stesso ordine come variabili data.frame sorgente.
Così come un hack di base si può solo ordinare nome variabili durante la creazione del data.frame:

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

Se avete bisogno di riordinare al termine del processo, poi organizzare() potrebbe essere la soluzione migliore.

+0

Grazie per questo suggerimento. Non ho chiarito la mia domanda, ma i dati reali contengono diverse dozzine di elementi ei valori con cui le faccette dovrebbero essere ordinate cambiano frequentemente, quindi il riordino manuale sarebbe piuttosto oneroso. – SlowLearner

Problemi correlati