Nakładanie histogramów za pomocą ggplot2 w R

125

Jestem nowy w R i próbuję wykreślić 3 histogramy na tym samym wykresie. Wszystko działało dobrze, ale mój problem polega na tym, że nie widać, gdzie nakładają się 2 histogramy - wyglądają raczej na obcięte.

Kiedy tworzę wykresy gęstości, wygląda to idealnie: każda krzywa jest otoczona czarną linią ramki, a kolory wyglądają inaczej, gdy krzywe się nakładają.

Czy ktoś może mi powiedzieć, czy coś podobnego można osiągnąć za pomocą histogramów z pierwszego rysunku? Oto kod, którego używam:

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
źródło
3
Hiperłącza do histogramu i wykresu gęstości są zepsute
Daghan ---

Odpowiedzi:

115

Twój aktualny kod:

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

mówi, ggplotaby skonstruować jeden histogram przy użyciu wszystkich wartości w, f0a następnie pokolorować słupki tego pojedynczego histogramu zgodnie ze zmienną utt.

Zamiast tego chcesz utworzyć trzy oddzielne histogramy z mieszaniem alfa, aby były widoczne przez siebie. Więc prawdopodobnie chcesz użyć trzech oddzielnych wywołań geom_histogram, z których każdy otrzymuje własną ramkę danych i wypełnia:

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

Oto konkretny przykład z danymi wyjściowymi:

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)

co daje coś takiego:

wprowadź opis obrazu tutaj

Edytowano w celu poprawienia literówek; chciałeś wypełnić, a nie kolor.

joran
źródło
7
To nie działa, gdy podzbiór ma inny rozmiar. Masz jakiś pomysł, jak rozwiązać ten problem? (Np. Użyj danych z 100 punktami na „a”, 50 na „b”).
Jorge Leitao
3
Jedną z wad tego podejścia jest to, że miałem trudności z wyświetleniem legendy (choć mogło to wynikać tylko z mojego braku wiedzy). Druga odpowiedź poniżej @kohske domyślnie wyświetli legendę, którą można następnie zmodyfikować (wraz z określonymi kolorami wyświetlanymi na histogramie) za pomocą np scale_fill_manual().
Michael Ohlrogge,
1
dokładnie, jak możemy dodać do tego legendę?
shenglih
1
@shenglih Jak na legendę, odpowiedź Kohske poniżej jest lepsza. Jego odpowiedź jest również ogólnie lepsza.
joran
skąd pochodzi f0?
Alan
258

Korzystając z przykładowych danych @ joran,

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

zwróć uwagę, że domyślną pozycją geom_histogramjest „stos”.

patrz „regulacja pozycji” na tej stronie:

docs.ggplot2.org/current/geom_histogram.html

kohske
źródło
30
Myślę, że to powinna być najlepsza odpowiedź, ponieważ pozwala uniknąć powtarzania kodu
kfor
6
position = 'identity'to nie tylko bardziej czytelna odpowiedź, ale ładniej żeluje w przypadku bardziej skomplikowanych wątków, takich jak mieszane wywołania aes()i aes_string().
rensa
2
Ta odpowiedź również automatycznie wyświetli legendę dla kolorów, podczas gdy odpowiedź @joran nie. Legendę można następnie zmodyfikować za pomocą np scale_fill_manual(). Ta funkcja może być również używana do modyfikowania kolorów na histogramach.
Michael Ohlrogge,
4
Upewnij się również, że zmienna użyta w programie filljest czynnikiem.
hhh
9
Osobiście uważam, że stackoverflow powinien najpierw wymienić najbardziej pozytywną odpowiedź. „Prawidłowa odpowiedź” reprezentuje tylko opinię jednej osoby.
daknowles
25

Chociaż do wykreślenia wielu / nakładających się histogramów w ggplot2 potrzeba tylko kilka linii, wyniki nie zawsze są zadowalające. Aby oko mogło rozróżniać histogramy, konieczne jest właściwe użycie granic i kolorów .

Następujące funkcje równoważą kolory granic, nieprzezroczystości i nałożone wykresy gęstości, aby umożliwić widzowi rozróżnienie między rozkładami .

Pojedynczy histogram :

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

Wielokrotny histogram :

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

Zastosowanie :

Po prostu przekaż ramkę danych do powyższych funkcji wraz z żądanymi argumentami:

plot_histogram(iris, 'Sepal.Width')

wprowadź opis obrazu tutaj

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

wprowadź opis obrazu tutaj

Dodatkowy parametr w plot_multi_histogram to nazwa kolumny zawierającej etykiety kategorii.

Możemy to zobaczyć bardziej dramatycznie, tworząc ramkę danych z wieloma różnymi sposobami dystrybucji :

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

Przekazywanie ramki danych jak poprzednio (i poszerzanie wykresu za pomocą opcji):

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

wprowadź opis obrazu tutaj

Cybernetyczny
źródło
1
Jest to bardzo przydatne i miejmy nadzieję, że przyciągnie więcej uwagi.
Edward Tyler,
2
@EdwardTyler Bardzo prawda. Chciałbym móc zagłosować za tym więcej niż raz!
ayePete