2012-04-22 19 views
5

Desidero colorare gli sfondi di un diagramma di sfaccettatura ggplot2 in base al valore indicato in una particolare colonna. Usando le risposte alle domande precedenti che ho già chiesto, sono riuscito a mettere insieme ciò di cui avevo bisogno insieme. @ la risposta di joran alla domanda this è stata particolarmente utile in quanto illustra la tecnica di creazione di un frame dati separato da passare a ggplot.Programmazione dei colori con programmazione scale_fill_manual ggplot

Tutto questo funziona bene abbastanza, dando l'output mostrato nell'immagine seguente: facets coloured by region

Ecco il codice che ho usato per generare la trama di cui sopra:

# User-defined variables go here 

list_of_names <- c('aa','bb','cc','dd','ee','ff') 
list_of_regions <- c('europe','north america','europe','asia','asia','japan') 

# Libraries 

require(ggplot2) 
require(reshape) 

# Create random data with meaningless column names 
set.seed(123) 
myrows <- 30 
mydf <- data.frame(date = seq(as.Date('2012-01-01'), by = "day", length.out = myrows), 
        aa = runif(myrows, min=1, max=2), 
        bb = runif(myrows, min=1, max=2), 
        cc = runif(myrows, min=1, max=2), 
        dd = runif(myrows, min=1, max=2), 
        ee = runif(myrows, min=1, max=2), 
        ff = runif(myrows, min=1, max=2)) 

# Transform data frame from wide to long 

mydf <- melt(mydf, id = c('date')) 
mydf$region <- as.character("unassigned") 

# Assign regional label 

for (ii in seq_along(mydf$date)) { 
    for (jj in seq_along(list_of_names)) { 
     if(as.character(mydf[ii,2]) == list_of_names[jj]) {mydf$region[ii] <- as.character(list_of_regions[jj])} 
    } 
} 

# Create data frame to pass to ggplot for facet colours 
mysubset <- unique(mydf[,c('variable','region')]) 
mysubset$value <- median(mydf$value) # a dummy value but one within the range used in the data frame 
mysubset$date <- as.Date(mydf$date[1]) # a dummy date within the range used 

# ... And plot 
p1 <- ggplot(mydf, aes(y = value, x = date, group = variable)) + 
    geom_rect(data = mysubset, aes(fill = region), xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf, alpha = 0.3) + 
    scale_fill_manual(values = c("japan" = "red", "north america" = "green", "asia" = "orange", "europe" = "blue")) + 
    geom_line() + 
    facet_wrap(~ variable, ncol = 2) 

print (p1) 

Lo script del mondo reale in direzione che sto lavorando è destinato ad essere usato per molti gruppi diversi contenenti molte serie di dati diversi, quindi questo script sarà duplicato molte volte, con solo le variabili che cambiano.

Ciò rende importante che gli elementi definiti dall'utente siano chiaramente accessibili per la modifica, motivo per cui le variabili list_of_names e list_of_regions vengono posizionate direttamente all'inizio del file. (Naturalmente, sarebbe meglio non aver bisogno di cambiare lo script, ma piuttosto definire questi elenchi come file esterni o passarli allo script come argomenti.) Ho provato a generalizzare la soluzione usando questi due loop for per assegnare il regioni. Per un po 'ho cercato di ottenere una soluzione più centrata sull'R utilizzando le funzioni apply ma non riuscivo a farlo funzionare, così ho rinunciato e bloccato con quello che sapevo.

Tuttavia, nel mio codice così com'è, la chiamata scale_fill_manual deve essere passata in modo esplicito per definire i colori di riempimento, ad esempio 'europe' = 'blue'. Queste variabili variano a seconda dei dati che sto elaborando, quindi con lo script nella sua forma attuale, dovrò modificare manualmente la parte ggplot dello script per ciascun gruppo di serie di dati. So che sarebbe molto dispendioso in termini di tempo e ho il forte sospetto che sarebbe anche molto soggetto a errori.

D. Idealmente mi piacerebbe essere in grado di estrarre programmazione e definire i valori richiesti per l'scale_fill_manual chiamata da una lista precedentemente dichiarato di valori (in questo caso da list_of_regions) abbinato ad una lista precedentemente dichiarato di colori, ma Non riesco a pensare a un modo per raggiungere questo obiettivo. Hai qualche idea?

+0

E 'possibile se si dispone di un elenco di regione e un elenco di colore. Dov'è la lista dei colori? – kohske

+0

Er, um, non ne ho ancora definito uno! Un elenco di colori arbitrari sarebbe sufficiente per un esempio. – SlowLearner

risposta

4

Questo aiuto?

cols <- rainbow(nrow(mtcars)) 
mtcars$car <- rownames(mtcars) 

ggplot(mtcars, aes(mpg, disp, colour = car)) + geom_point() + 
    scale_colour_manual(limits = mtcars$car, values = cols) + 
    guides(colour = guide_legend(ncol = 3)) 

enter image description here

+0

Grazie per questo @kohske. conforme a v0.90! Giusto per chiarire, se volessi specificare i colori per ciascuna delle auto, come potrei affrontarlo? (Mi scuso - ho detto che una lista arbitraria di colori andrebbe bene. Avrei dovuto dire che non mi interessa quali colori sono usati, ma mi piacerebbe poter definire il colore per ogni oggetto, in questo caso ciascuno modello di auto.) – SlowLearner

+0

Poi modifica i 'cols' come preferisci. Ciò che è importante è la corrispondenza di 'limits' e' values' in 'scale_colour_manual'. – kohske

+0

Sembra semplice. Quindi 'limits' specifica l'elemento e' values' il colore, in modo che il primo elemento nella lista 'limits' sia assegnato al primo colore nell'elenco' values', e così via? – SlowLearner