Накладання гістограм з ggplot2 в R


124

Я новачок у R і намагаюся побудувати 3 гістограми на одному графіку. Все працювало чудово, але моя проблема полягає в тому, що ви не бачите, де 2 гістограми перекриваються - вони виглядають досить відрізаними.

Коли я роблю графіки щільності, це виглядає ідеально: кожна крива оточена чорною лінією рамки, а кольори виглядають по-різному там, де криві перетинаються.

Чи може хтось мені сказати, чи можна щось подібне досягти за допомогою гістограм на 1-му малюнку? Це код, який я використовую:

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
Гіперпосилання на гістограму та графік щільності порушені
Даган ---

Відповіді:


115

Ваш поточний код:

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

говорить ggplotпро побудову однієї гістограми, використовуючи всі значення в, f0а потім пофарбуйте смуги цієї єдиної гістограми відповідно до змінної utt.

Замість цього потрібно створити три окремі гістограми з альфа-змішуванням, щоб вони були видні один одному. Отже, ви, мабуть, хочете використовувати три окремі дзвінки geom_histogram, де кожен отримує власний кадр даних та заповнює:

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

Ось конкретний приклад з деяким результатом:

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)

яка виробляє щось подібне:

введіть тут опис зображення

Відредаговано для виправлення помилок друку; ви хотіли заповнити, а не кольором.


7
Це не працює, коли підмножина має різний розмір. Будь-яка ідея, як вирішити це? (Наприклад, використовуйте дані зі 100 балами на "a", 50 на "b").
Хорхе Лейтао

3
Одним із недоліків цього підходу є те, що у мене виникли труднощі з його відображенням легенди (хоча це могло бути просто через мою нестачу знань). Інший відповідь нижче по @kohske за замовчуванням буде відображатися легенда , яка потім може бути змінена (поряд з конкретними квітами відображається на гістограмі) з, наприклад scale_fill_manual().
Michael Ohlrogge

1
як саме ми можемо додати легенду до цього ??
shenglih

1
@shenglih Для легенди відповідь kohske нижче є кращою. Його відповідь також просто загалом краща.
Жоран

звідки походить f0?
Алан

256

Використовуючи зразкові дані @ joran,

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

зауважте, що за замовчуванням позиція geom_histogram"стек".

див. "коригування положення" цієї сторінки:

docs.ggplot2.org/current/geom_histogram.html


30
Я думаю, що це має бути головна відповідь, оскільки вона уникає повторення коду
kfor

6
position = 'identity'це не просто читабельніша відповідь, вона гаразд виходить із складнішими сюжетами, такими як змішані дзвінки на aes()та aes_string().
rensa

2
Ця відповідь також автоматично відображатиме легенду про кольори, тоді як відповідь від @joran не буде. Легенда може бути змінена з допомогою, наприклад scale_fill_manual(). Ця функція також може бути використана для зміни кольорів у гістограмах.
Michael Ohlrogge

4
Також переконайтеся, що змінна, що використовується, fillє фактором.
hhh

9
Особисто я думаю, що stackoverflow повинен спочатку перелічити найбільш схвалену відповідь. "Правильна відповідь" представляє лише думку однієї людини.
daknowles

25

Хоча для побудови декількох / перекриваються гістограм у ggplot2 потрібно лише кілька рядків, результати не завжди є задовільними. Потрібно належним чином використовувати рамки та забарвлення, щоб око могло розмежовувати гістограми .

Наступні функції врівноважують кольори меж, непрозорість і накладені графіки щільності, щоб глядач міг диференціювати розподіли .

Єдина гістограма :

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

Кілька гістограм :

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

Використання :

Просто перенесіть ваш кадр даних у вказані вище функції разом із потрібними аргументами:

plot_histogram(iris, 'Sepal.Width')

введіть тут опис зображення

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

введіть тут опис зображення

Додатковий параметр в plot_multi_histogram цього ім'я стовпця , що містять мітки категорій.

Ми можемо побачити це більш кардинально, створивши кадр даних з багатьма різними засобами розповсюдження :

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

Передача кадру даних як раніше (і розширення діаграми за допомогою параметрів):

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

введіть тут опис зображення


1
Це дуже корисно, сподіваємось, отримує більше уваги.
Едвард Тайлер

2
@EdwardTyler Дуже правда. Я б хотів, щоб я міг підтримати це не раз!
ayePete
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.