ggplot2 เพิ่มข้อมูลจากกรอบข้อมูลเพิ่มเติมถัดจากพล็อต

ฉันต้องการที่จะขยาย boxplots ของฉันด้วยข้อมูลเพิ่มเติม นี่คือตัวอย่างการทำงานของ ggplot2:

library(ggplot2)

ToothGrowth$dose <- as.factor(ToothGrowth$dose)

# Basic box plot
p <- ggplot(ToothGrowth, aes(x=dose, y=len)) + 
  geom_boxplot()
# Rotate the box plot
p + coord_flip()

ฉันต้องการเพิ่มข้อมูลเพิ่มเติมจากเฟรมข้อมูลแยกต่างหาก ตัวอย่างเช่น:

extra <- data.frame(dose=factor(c(0.5,1,2)), label=c("Label1", "Label2", "Label3"), n=c("n=42","n=52","n=35"))

> extra
  dose  label    n
1  0.5 Label1 n=42
2    1 Label2 n=52
3    2 Label3 n=35

ฉันต้องการสร้างรูปต่อไปนี้โดยที่ข้อมูลของแต่ละโดส (ปัจจัย) อยู่นอกพล็อตและสอดคล้องกับแต่ละระดับของโดส (ฉันทำสิ่งนี้ใน PowerPoint เป็นตัวอย่าง):

ป้อนคำอธิบายรูปภาพที่นี่

คำแนะนำใด ๆ ที่ชื่นชมอย่างมาก!

ขอแสดงความนับถือ ลุค

แก้ไข: ขอบคุณมากสำหรับคำตอบของคุณ! สมบูรณ์แบบ. ผมอยากจะขอคำแนะนำขยายคำถามเบื้องต้นครับ

แล้วส่วนขยายนี้ที่ฉันใช้การเติมเพื่อแบ่งขนาดยาออกเป็นสองกลุ่มล่ะ?

ToothGrowth$dose <- as.factor(ToothGrowth$dose)
ToothGrowth$group <- head(rep(1:2, 100), dim(ToothGrowth)[1])
ToothGrowth$group <- factor(ToothGrowth$group)

 p <- ggplot(ToothGrowth, aes(x=dose, y=len, fill=group)) + 
     geom_boxplot()
 # Rotate the box plot
 p + coord_flip()

extra <- data.frame(
  dose=factor(rep(c(0.5,1,2), each=2)), 
  group=factor(rep(c(1:2), 3)), 
  label=c("Label1A", "Label1B", "Label2A", "Label2B", "Label3A", "Label3B"), 
  n=c("n=12","n=30","n=20", "n=32","n=15","n=20")
)

เป็นไปได้หรือไม่ที่จะจัดข้อมูลจากกรอบข้อมูลใหม่ (พิเศษ 6 แถว) ให้สอดคล้องกับแต่ละขนาดยา/กลุ่มรวมกัน

ไชโย ลุค


person Luc    schedule 09.08.2018    source แหล่งที่มา


คำตอบ (1)


เราสามารถใช้ geom_text กับ clip = "off" ภายใน coord_flip:

ggplot(ToothGrowth, aes(x=dose, y=len)) +
    geom_boxplot() +
    geom_text(
        y = max(ToothGrowth$len) * 1.1,
        data = extra,
        aes(x = dose, label = sprintf("%s\n%s", label, n)),
        hjust = 0) +
    coord_flip(clip = "off") +
    theme(plot.margin = unit(c(1, 5, 0.5, 0.5), "lines"))

ป้อนคำอธิบายรูปภาพที่นี่

คำอธิบาย: เราวางข้อความไว้นอกพื้นที่พล็อตด้วย geom_text และปิดการใช้งานการตัดภาพด้วย clip = "off" ภายใน coord_flip สุดท้ายนี้ เราเพิ่มระยะขอบของพล็อตเพื่อรองรับป้ายกำกับเพิ่มเติม คุณสามารถปรับตำแหน่งแนวตั้ง y ในระยะขอบ (ดังนั้นตำแหน่งแนวนอนในพล็อตเนื่องจากการพลิกพิกัด) โดยการเปลี่ยนปัจจัยใน y = max(ToothGrowth$len) * 1.1


เพื่อตอบสนองต่อการแก้ไขของคุณ นี่คือความเป็นไปได้

extra <- data.frame(
  dose=factor(rep(c(0.5,1,2), each=2)),
  group=factor(rep(c(1:2), 3)),
  label=c("Label1A", "Label1B", "Label2A", "Label2B", "Label3A", "Label3B"),
  n=c("n=12","n=30","n=20", "n=32","n=15","n=20")
)

library(tidyverse)
ToothGrowth %>%
    mutate(
        dose = as.factor(dose),
        group = as.factor(rep(1:2, nrow(ToothGrowth) / 2))) %>%
    ggplot(aes(x = dose, y = len, fill = group)) +
    geom_boxplot(position = position_dodge(width = 1)) +
    geom_text(
        data = extra %>%
            mutate(
                dose = as.factor(dose),
                group = as.factor(group),
                ymax = max(ToothGrowth$len) * 1.1),
        aes(x = dose, y = ymax, label = sprintf("%s\n%s", label, n)),
        position = position_dodge(width = 1),
        size = 3,
        hjust = 0) +
    coord_flip(clip = "off", ylim = c(0, max(ToothGrowth$len))) +
    theme(
        plot.margin = unit(c(1, 5, 0.5, 0.5), "lines"),
        legend.position = "bottom")

ป้อนคำอธิบายรูปภาพที่นี่

ความคิดเห็นบางส่วน:

  1. เราตรวจสอบให้แน่ใจว่าป้ายกำกับตรงกับแถบหลบโดยใช้ position_dodge(with = 1) ภายใน geom_text และ geom_boxplot
  2. ดูเหมือนว่า position_dodge ไม่ชอบ y ทั่วโลก (นอก aes) ดังนั้นเราจึงรวมตำแหน่ง y ของป้ายกำกับไว้ใน extra และใช้ตำแหน่งดังกล่าวภายใน aes ด้วยเหตุนี้ เราจึงต้องจำกัดช่วงของแกน y อย่างชัดเจน เราสามารถทำได้ภายใน coord_flip ด้วย ylim = c(0, max(ToothGrowth$len))
person Maurits Evers    schedule 09.08.2018
comment
ขอบคุณมาก! ตรงกับที่ฉันต้องการ! - person Luc; 10.08.2018
comment
สวัสดี Maurits คุณช่วยดูปัญหาเพิ่มเติมของฉันได้ไหม ดูการแก้ไขในโพสต์ต้นฉบับ - person Luc; 10.08.2018
comment
คุณคือตำนาน! - person Luc; 10.08.2018