Sovrapposizione di istogrammi con ggplot2 in R


124

Sono nuovo in R e sto cercando di tracciare 3 istogrammi sullo stesso grafico. Tutto ha funzionato bene, ma il mio problema è che non vedi dove 2 istogrammi si sovrappongono: sembrano piuttosto tagliati.

Quando creo grafici di densità, sembra perfetto: ogni curva è circondata da una linea di cornice nera e i colori hanno un aspetto diverso dove le curve si sovrappongono.

Qualcuno può dirmi se è possibile ottenere qualcosa di simile con gli istogrammi nella prima immagine? Questo è il codice che sto usando:

lowf0 <-read.csv (....)
mediumf0 <-read.csv (....)
highf0 <-read.csv(....)
lowf0$utt<-'low f0'
mediumf0$utt<-'medium f0'
highf0$utt<-'high f0'
histogram<-rbind(lowf0,mediumf0,highf0)
ggplot(histogram, aes(f0, fill = utt)) + geom_histogram(alpha = 0.2)

3
I collegamenti ipertestuali all'istogramma e al
— grafico

Risposte:


115

Il tuo codice attuale:

ggplot(histogram, aes(f0, fill = utt)) + geom_histogram(alpha = 0.2)

sta dicendo ggplotdi costruire un istogramma usando tutti i valori in f0e poi colorare le barre di questo singolo istogramma in base alla variabile utt.

Quello che vuoi invece è creare tre istogrammi separati, con alpha blending in modo che siano visibili l'uno attraverso l'altro. Quindi probabilmente vorrai usare tre chiamate separate a geom_histogram, in cui ognuna ottiene il proprio frame di dati e riempimento:

ggplot(histogram, aes(f0)) + 
    geom_histogram(data = lowf0, fill = "red", alpha = 0.2) + 
    geom_histogram(data = mediumf0, fill = "blue", alpha = 0.2) +
    geom_histogram(data = highf0, fill = "green", alpha = 0.2) +

Ecco un esempio concreto con qualche output:

dat <- data.frame(xx = c(runif(100,20,50),runif(100,40,80),runif(100,0,30)),yy = rep(letters[1:3],each = 100))

ggplot(dat,aes(x=xx)) + 
    geom_histogram(data=subset(dat,yy == 'a'),fill = "red", alpha = 0.2) +
    geom_histogram(data=subset(dat,yy == 'b'),fill = "blue", alpha = 0.2) +
    geom_histogram(data=subset(dat,yy == 'c'),fill = "green", alpha = 0.2)

che produce qualcosa del genere:

inserisci qui la descrizione dell'immagine

Modificato per correggere errori di battitura; volevi riempimento, non colore.


7
Questo non funziona quando il sottoinsieme ha dimensioni diverse. Qualche idea su come affrontare questo? (Ad esempio, utilizzare dati con 100 punti su "a", 50 su "b").
— Jorge Leitao

3
Uno svantaggio di questo approccio è che ho avuto difficoltà a far visualizzare una leggenda (anche se questo potrebbe essere dovuto solo alla mia mancanza di conoscenza). L'altra risposta sotto di @kohske mostrerà per impostazione predefinita una legenda che può quindi essere modificata (insieme ai colori specifici visualizzati sull'istogramma) con, ad es scale_fill_manual().
— Michael Ohlrogge,

1
esattamente, come possiamo aggiungere una leggenda a questo?
— shenglih

1
@shenglih Per una leggenda, la risposta di kohske di seguito è migliore. Anche la sua risposta è generalmente migliore.
— joran

da dove viene f0?
— Alan,

256

Utilizzando i dati di esempio di @ joran,

ggplot(dat, aes(x=xx, fill=yy)) + geom_histogram(alpha=0.2, position="identity")

nota che la posizione predefinita di geom_histogramè "stack".

vedere "regolazione della posizione" di questa pagina:

docs.ggplot2.org/current/geom_histogram.html


30
Penso che questa dovrebbe essere la risposta migliore poiché evita di ripetere il codice
— k per il

6
position = 'identity'non è solo una risposta più leggibile, ma si integra meglio con trame più complicate, come chiamate miste a aes()e aes_string().
— rensa

2
Questa risposta mostrerà automaticamente anche una legenda per i colori, mentre la risposta di @joran no. La legenda può quindi essere modificata utilizzando, ad es scale_fill_manual(). Questa funzione può essere utilizzata anche per modificare i colori negli istogrammi.
— Michael Ohlrogge,

4
Inoltre, assicurati che la variabile utilizzata in fillsia un fattore.
— hhh

9
Personalmente penso che stackoverflow dovrebbe elencare prima la risposta più votata. La "risposta corretta" rappresenta solo l'opinione di una persona.
— daknowles

25

Sebbene siano necessarie solo poche righe per tracciare istogrammi multipli / sovrapposti in ggplot2, i risultati non sono sempre soddisfacenti. Ci deve essere un uso corretto dei bordi e della colorazione per garantire che l'occhio possa distinguere tra gli istogrammi .

Le seguenti funzioni bilanciano i colori dei bordi, le opacità e i grafici di densità sovrapposti per consentire allo spettatore di differenziare le distribuzioni .

Istogramma singolo :

plot_histogram <- function(df, feature) {
    plt <- ggplot(df, aes(x=eval(parse(text=feature)))) +
    geom_histogram(aes(y = ..density..), alpha=0.7, fill="#33AADE", color="black") +
    geom_density(alpha=0.3, fill="red") +
    geom_vline(aes(xintercept=mean(eval(parse(text=feature)))), color="black", linetype="dashed", size=1) +
    labs(x=feature, y = "Density")
    print(plt)
}

Istogramma multiplo :

plot_multi_histogram <- function(df, feature, label_column) {
    plt <- ggplot(df, aes(x=eval(parse(text=feature)), fill=eval(parse(text=label_column)))) +
    geom_histogram(alpha=0.7, position="identity", aes(y = ..density..), color="black") +
    geom_density(alpha=0.7) +
    geom_vline(aes(xintercept=mean(eval(parse(text=feature)))), color="black", linetype="dashed", size=1) +
    labs(x=feature, y = "Density")
    plt + guides(fill=guide_legend(title=label_column))
}

Utilizzo :

Passa semplicemente il tuo frame di dati nelle funzioni precedenti insieme agli argomenti desiderati:

plot_histogram(iris, 'Sepal.Width')

inserisci qui la descrizione dell'immagine

plot_multi_histogram(iris, 'Sepal.Width', 'Species')

inserisci qui la descrizione dell'immagine

Il parametro aggiuntivo in plot_multi_histogram è il nome della colonna contenente le etichette delle categorie.

Possiamo vederlo in modo più drammatico creando un dataframe con molti mezzi di distribuzione diversi :

a <-data.frame(n=rnorm(1000, mean = 1), category=rep('A', 1000))
b <-data.frame(n=rnorm(1000, mean = 2), category=rep('B', 1000))
c <-data.frame(n=rnorm(1000, mean = 3), category=rep('C', 1000))
d <-data.frame(n=rnorm(1000, mean = 4), category=rep('D', 1000))
e <-data.frame(n=rnorm(1000, mean = 5), category=rep('E', 1000))
f <-data.frame(n=rnorm(1000, mean = 6), category=rep('F', 1000))
many_distros <- do.call('rbind', list(a,b,c,d,e,f))

Passaggio del frame di dati come prima (e ampliamento del grafico utilizzando le opzioni):

options(repr.plot.width = 20, repr.plot.height = 8)
plot_multi_histogram(many_distros, 'n', 'category')

inserisci qui la descrizione dell'immagine


1
Questo è molto utile, si spera che riceva più attenzione.
— Edward Tyler

2
@EdwardTyler Molto vero. Vorrei poter votare questo più di una volta!
— ayePete
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.