2016-05-17 21 views
8

Sto provando a colorare i nastri in ggplot2. Quando utilizzo geom_ribbon, sono in grado di specificare ymin e ymax e un colore di riempimento. Quello che ora fa è colorare tutto ciò che è tra ymin e ymax senza riguardo al limite superiore o al limite inferiore.ggplot2: comportamento del colore di riempimento di geom_ribbon

Esempio (modificato da Internet):

library("ggplot2") 
# Generate data (level2 == level1) 
huron <- data.frame(year = 1875:1972, level = as.vector(LakeHuron), level2 = as.vector(LakeHuron)) 

# Change Level2 
huron[1:50,2] <- huron[1:50,2]+100 
huron[50:90,2] <- huron[50:90,2]-100 

h <- ggplot(huron, aes(year)) 

h + 
    geom_ribbon(aes(ymin = level, ymax = level2), fill = "grey80") + 
    geom_line(aes(y = level)) + geom_line(aes(y=level2)) 

si tradurrà in questo grafico: enter image description here

mi piacerebbe riempire l'area, dove (ymin> ymax), con un colore diverso di dove (ymin < ymax). Nei miei dati reali ho esportato e importato valori. Lì, vorrei colorare l'area in cui l'esportazione è più alta del verde importato, dove l'importazione è più grande dell'esportazione. Voglio che il nastro sia rosso.

Alternativa: vorrei che geom_ribbon riempisse solo l'area, dove ymax> ymin.

Qualcuno sa come è fatto?

Grazie per il vostro aiuto.

risposta

7

Un'opzione che non richiede la creazione manuale di un'altra colonna consiste nel fare la logica all'interno di aes(fill = stesso;

## fill dependent on level > level2 
h + 
    geom_ribbon(aes(ymin = level, ymax = level2, fill = level > level2)) + 
    geom_line(aes(y = level)) + geom_line(aes(y=level2)) + 
    scale_fill_manual(values=c("red", "green"), name="fill") 

filled conditional on level > level2

Oppure, se si vuole solo riempire in base a tale condizione sia vera,

## fill dependent on level > level2, no fill otherwise 
h + 
    geom_ribbon(aes(ymin = level, ymax = level2, fill = ifelse(level > level2, TRUE, NA))) + 
    geom_line(aes(y = level)) + geom_line(aes(y=level2)) + 
    scale_fill_manual(values=c("green"), name="fill") 

filled conditional on level > level2, not otherwise

presumo la mancanza di riempimento interpolati sembra avere qualcosa a che fare con la versione ggplot2, poiché ho lo stesso problema con il codice @ barbabietola

## @beetroot's answer 
huron$id <- 1:nrow(huron) 
huron$group <- ifelse(huron$id <= 50, "A", "B") 

h <- ggplot(huron, aes(year)) 
h + 
    geom_ribbon(aes(ymin = level, ymax = level2, fill = group)) + 
    geom_line(aes(y = level)) + geom_line(aes(y = level2))  

@beetroot's answer

ottengo @ uscita dell'immagine di Manuk durante l'esecuzione di quel codice senza logica in aes(fill =.

+0

Wow, è fantastico, grazie mille! È esattamente quello che volevo, in quanto posso sostanzialmente mettere una condizione in "fill =". Comunque lascerò aperta la richiesta di modifica perché non è perfetta: il riempimento non può essere applicato perfettamente al punto di intersezione. (Questa volta nessun problema per me) Inoltre, penso ancora che la logica di riempimento in ggplot2 debba essere cambiata. – ManuK

+0

Super utile! C'è un modo per ottenere lo stesso risultato con i dati nel formato lungo? Ad esempio, con i dati impostati come: Anno, Livello (1 o 2), Valore. Posso arrivare fino a: h + geom_line (aes (y = Value, group = Level) ma non riesco a capire come aggiungere nel layer geom_ribbon() con questa struttura. –

+1

Non facilmente, non credo . 'ggplot2' si aspetta colonne, quindi devi avere una colonna da usare come i valori' ymin' e 'ymax'.È abbastanza semplice per' tidyr :: spread() 'i tuoi dati lunghi nel formato richiesto però. –

5

È possibile aggiungere una variabile di raggruppamento ai dati che è possibile utilizzare per specificare il colore di riempimento. Tuttavia, il problema è il punto in cui le due linee si intersecano in quanto deve essere inclusa in entrambi i gruppi per evitare eventuali lacune.

Quindi, prima trovare questa riga ..

huron[huron$level == huron$level2,] 

> huron[huron$level == huron$level2,] 
    year level level2 
50 1924 577.79 577.79 
... 

e aggiungerlo ai dati una volta di più:

huron <- rbind(huron, huron[huron$year == 1924,]) 
huron <- huron[order(huron$year),] 

quindi aggiungere una colonna id base l'indice di riga, e impostare i gruppi in base sul numero di riga del 1924:

huron$id <- 1:nrow(huron) 
huron$group <- ifelse(huron$id <= 50, "A", "B") 

h <- ggplot(huron, aes(year)) 
h + 
    geom_ribbon(aes(ymin = level, ymax = level2, fill = group)) + 
    geom_line(aes(y = level)) + geom_line(aes(y = level2)) 

enter image description here

+0

grazie mille per la risposta, questo funziona. Nel mio caso, tuttavia, non è molto utile a causa dei seguenti problemi: 1. Vorrei aggiungere più nastri, quindi avrei bisogno di aggiungere un bel po 'di colonne "workaround". 2. I punti in cui le linee si incontrano non sono realmente visibili nei dati, quindi dovrei calcolare questi punti e aggiungerli al database (due volte). Ho sperato in una soluzione facile, ma sembra essere più complicato di un facile riempimento condizionale. :-) – ManuK

+0

@ManuK sì, specialmente il 2. problema è difficile da risolvere per quanto ne so e sfortunatamente non posso aiutarti al momento. Ma forse qualcun altro troverà un'altra risposta? Forse [questo] (https://learnr.wordpress.com/2009/10/22/ggplot2-two-color-xy-area-combo-chart/) post sul blog ti dà alcune idee – beetroot

+0

Ho presentato il problema come una funzionalità richiesta al github ggplot2. Spero che sarà implementato in una versione futura di ggplot2 [collegamento a richiesta] (https://github.com/hadley/ggplot2/issues/1642) – ManuK

1

Come muoversi il problema che ho avuto con i non-interpolata fill, è possibile utilizzare due (o n) nastri

h <- ggplot() + 
    geom_ribbon(data = huron[huron$level >= huron$level2, ], aes(x = year, ymin = level, ymax = level2), fill="green") + 
    geom_ribbon(data = huron[huron$level <= huron$level2, ], aes(x = year, ymin = level, ymax = level2), fill="red") + 
    geom_line(data = huron, aes(x = year, y = level)) + 
    geom_line(data = huron, aes(x = year, y = level2)) 
h 

Fill is interpolated now

qualsiasi condizione di utilizzare in aes(fill = sta per costringere ad un fattore, quindi sembra che si applichi solo dove sono effettivamente i dati. Non penso che questo sia un bug ggplot2, penso che questo sia un comportamento previsto.

Problemi correlati