การซ้อนทับฮิสโตแกรมด้วย ggplot2 ใน R


125

ฉันยังใหม่กับ 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
ไฮเปอร์ลิงก์ไปยังฮิสโตแกรมและพล็อตความหนาแน่นแตก
Daghan ---

คำตอบ:


115

รหัสปัจจุบันของคุณ:

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

จะบอกggplotในการสร้างหนึ่ง histogram ใช้ค่าทั้งหมดที่อยู่ในf0และแล้วสีแท่ง histogram 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")
Jorge Leitao

3
ข้อเสียอย่างหนึ่งของวิธีนี้คือฉันมีปัญหาในการแสดงตำนาน (แม้ว่าอาจเป็นเพราะฉันขาดความรู้ก็ตาม) คำตอบอื่น ๆ ด้านล่างโดย @kohske จะเริ่มต้นด้วยการแสดงตำนานซึ่งจากนั้นจะสามารถแก้ไข (พร้อมกับสีที่เฉพาะเจาะจงที่แสดงบนกราฟ) scale_fill_manual()ด้วยเช่น
Michael Ohlrogge

1
เราจะเพิ่มตำนานนี้ได้อย่างไร ??
shenglih

1
@shenglih สำหรับตำนานคำตอบของ kohske ด้านล่างดีกว่า คำตอบของเขาก็ดีกว่าโดยทั่วไป
joran

f0 มาจากไหน?
Alan

258

ใช้ข้อมูลตัวอย่างของ @ 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
ฉันคิดว่านี่ควรเป็นคำตอบอันดับต้น ๆ เนื่องจากหลีกเลี่ยงการใช้รหัสซ้ำ
k สำหรับ

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

การใช้งาน :

เพียงแค่ส่ง data frame ของคุณไปยังฟังก์ชันด้านบนพร้อมกับอาร์กิวเมนต์ที่ต้องการ:

plot_histogram(iris, 'Sepal.Width')

ใส่คำอธิบายภาพที่นี่

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

ใส่คำอธิบายภาพที่นี่

พารามิเตอร์พิเศษใน plot_multi_histogram เป็นชื่อของคอลัมน์ที่มีป้ายกำกับหมวดหมู่

เราสามารถเห็นสิ่งนี้ได้อย่างมากขึ้นโดยการสร้าง dataframe ด้วยวิธีการกระจายที่แตกต่างกัน :

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

การส่งผ่าน data frame เหมือนเดิม (และการขยายแผนภูมิโดยใช้ตัวเลือก):

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

ใส่คำอธิบายภาพที่นี่


1
สิ่งนี้มีประโยชน์มากหวังว่าจะได้รับความสนใจมากขึ้น
Edward Tyler

2
@EdwardTyler จริงมาก. ฉันหวังว่าฉันจะโหวตได้มากกว่าหนึ่งครั้ง!
ayePete
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.