Überlagern von Histogrammen mit ggplot2 in R.

124

Ich bin neu in R und versuche, 3 Histogramme auf demselben Diagramm zu zeichnen. Alles hat gut funktioniert, aber mein Problem ist, dass Sie nicht sehen, wo sich 2 Histogramme überlappen - sie sehen eher abgeschnitten aus.

Wenn ich Dichtediagramme erstelle, sieht es perfekt aus: Jede Kurve ist von einer schwarzen Rahmenlinie umgeben, und Farben sehen dort anders aus, wo sich Kurven überlappen.

Kann mir jemand sagen, ob mit den Histogrammen im 1. Bild etwas Ähnliches erreicht werden kann? Dies ist der Code, den ich verwende:

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)
Bloomy
quelle
3
Die Hyperlinks zum Histogramm und zum Dichtediagramm sind unterbrochen
Daghan ---

Antworten:

115

Ihr aktueller Code:

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

sagt ggplot, ein Histogramm mit allen Werten in zu erstellen f0und dann die Balken dieses einzelnen Histogramms entsprechend der Variablen zu färben utt.

Stattdessen möchten Sie drei separate Histogramme mit Alpha-Überblendung erstellen, sodass sie durcheinander sichtbar sind. Sie möchten also wahrscheinlich drei separate Aufrufe an verwenden geom_histogram, bei denen jeder seinen eigenen Datenrahmen erhält und ausfüllt:

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

Hier ist ein konkretes Beispiel mit einigen Ergebnissen:

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)

was so etwas hervorbringt:

Geben Sie hier die Bildbeschreibung ein

Bearbeitet, um Tippfehler zu beheben; Sie wollten füllen, nicht Farbe.

Joran
quelle
7
Dies funktioniert nicht, wenn die Teilmenge eine andere Größe hat. Irgendeine Idee, wie man das anspricht? (Verwenden Sie z. B. Daten mit 100 Punkten auf "a", 50 auf "b").
Jorge Leitao
3
Ein Nachteil dieses Ansatzes ist, dass ich Schwierigkeiten hatte, eine Legende anzuzeigen (obwohl dies nur auf meinen Mangel an Wissen zurückzuführen sein könnte). Die andere Antwort von @kohske unten zeigt standardmäßig eine Legende an, die dann (zusammen mit den im Histogramm angezeigten spezifischen Farben) mit z scale_fill_manual().
Michael Ohlrogge
1
Genau, wie können wir dem eine Legende hinzufügen?
Shenglih
1
@shenglih Für eine Legende ist die Antwort von kohske unten besser. Seine Antwort ist auch nur allgemein besser.
Jordan
woher kommt f0?
Alan
256

Unter Verwendung der Beispieldaten von @ joran

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

Beachten Sie, dass die Standardposition von geom_histogram"Stapel" ist.

siehe "Positionseinstellung" dieser Seite:

docs.ggplot2.org/current/geom_histogram.html

kohske
quelle
30
Ich denke, dies sollte die beste Antwort sein, da es vermeidet, Code zu wiederholen
kfor
6
position = 'identity'ist nicht nur eine besser lesbare Antwort, sondern lässt sich auch besser mit komplizierteren Plots wie gemischten Anrufen an aes()und kombinieren aes_string().
Rensa
2
Diese Antwort zeigt auch automatisch eine Legende zu den Farben an, während die Antwort von @joran dies nicht tut. Die Legende kann dann geändert werden mit z scale_fill_manual(). Diese Funktion kann auch verwendet werden, um die Farben in den Histogrammen zu ändern.
Michael Ohlrogge
4
Stellen Sie außerdem sicher, dass die in verwendete Variable fillein Faktor ist.
hhh
9
Persönlich denke ich, dass Stackoverflow zuerst die am besten bewertete Antwort auflisten sollte. Die "richtige Antwort" gibt nur die Meinung einer Person wieder.
Daknowles
25

Während nur wenige Linien erforderlich sind, um mehrere / überlappende Histogramme in ggplot2 zu zeichnen, sind die Ergebnisse nicht immer zufriedenstellend. Ränder und Farben müssen ordnungsgemäß verwendet werden, um sicherzustellen, dass das Auge zwischen Histogrammen unterscheiden kann .

Die folgenden Funktionen gleichen Randfarben, Opazitäten und überlagerte Dichtediagramme aus , damit der Betrachter zwischen Verteilungen unterscheiden kann .

Einzelhistogramm :

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

Mehrfachhistogramm :

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

Verwendung :

Übergeben Sie einfach Ihren Datenrahmen zusammen mit den gewünschten Argumenten an die oben genannten Funktionen :

plot_histogram(iris, 'Sepal.Width')

Geben Sie hier die Bildbeschreibung ein

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

Geben Sie hier die Bildbeschreibung ein

Der zusätzliche Parameter in plot_multi_histogram ist der Name der Spalte, die die Kategoriebeschriftungen enthält.

Wir können dies dramatischer sehen, indem wir einen Datenrahmen mit vielen verschiedenen Verteilungsmitteln erstellen :

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

Datenrahmen wie zuvor übergeben (und Diagramm mithilfe von Optionen erweitern):

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

Geben Sie hier die Bildbeschreibung ein

Kybernetisch
quelle
1
Dies ist sehr nützlich und wird hoffentlich mehr beachtet.
Edward Tyler
2
@ EdwardTyler Sehr wahr. Ich wünschte, ich könnte dies mehr als einmal positiv bewerten!
ayePete