是否可以使用 geom_text 将文本放在每个构面面板下方并将其与刻度线对齐?

Is it possible to use geom_text to put text below each facet panel and align it with the tick marks?

我在下面的 facet_wrap 图上添加了文本行(ind = 305,ind = 182 ...)。我正在寻找一种方法,使这些文本行位于每个方面面板中的刻度线下方。我已经搜索并尝试了许多包含 "put text outside the ploting area" 短语的选项,但我无法解决我的问题。

这是我用来生成情节的代码。有什么可行的选择吗?

ggplot(df1, aes(Sex, value)) +    
  geom_boxplot(aes(fill = Sex), alpha = 0.2) + 
  theme_bw() +    
  facet_wrap(.~trait.code, nrow = 2, scales = "free") +    
  geom_text(data = df2[df2$Sex == "Female",], aes(label = ind), size = 4, fontface="bold") +    
  geom_text(data = df2[df2$Sex == "Male",], aes(label = ind), size = 4, fontface="bold") +  
  theme(axis.title.x= element_blank(), 
        axis.title.y=element_blank(),
        legend.position="bottom", 
        axis.text.x = element_blank(), 
        panel.spacing.y = unit(2, "lines")) + 
  ggtitle("Any tittle")

这是数据的一个子集

df1 <- structure(list(Sex = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L,  1L,
1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,  2L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L,  2L, 2L, 2L,
2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L,  2L, 2L, 2L, 2L,
2L, 2L, 2L, 2L, 2L), .Label = c("Female", "Male" ), class = "factor"),
value = c(80L, 108L, 48L, 89L, 80L, 62L,  96L, 143L, 108L, 94L, 201L,
171L, 211L, 117L, 195L, 149L, 130L,  100L, 206L, 150L, 10L, 8L, 10L,
6L, 8L, 16L, 32L, 16L, 19L, 22L,  40L, 30L, 50L, 22L, 41L, 15L, 22L,
16L, 42L, 20L, 13L, 23L, 18L,  19L, 19L, 20L, 21L, 30L, 23L, 20L, 30L,
25L, 26L, 26L, 28L, 27L,  25L, 22L, 23L, 19L, 1L, 50L, 35L, 121L, 16L,
10L, 166L, 376L,  153L, 228L, 224L, 93L, 498L, 140L, 108L, 286L, 371L,
312L, 104L,  353L), trait.code = structure(c(1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L,  1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L,
2L,  2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L,  3L,
3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L,  4L, 4L,
4L, 4L, 4L, 4L, 4L, 4L), .Label = c("Tra1", "Tra2", "Tra3",  "Tra4"),
class = "factor")), class = "data.frame", row.names = c(NA, 
-80L))

df2 <- structure(
  list(
    trait.code = structure(
      c(1L, 1L, 2L, 2L, 3L, 3L, 4L, 4L),
      .Label = c("Tra1", "Tra2", "Tra3", "Tra4"),
      class = "factor"
    ),
    Sex = c("Male", "Female", "Male", "Female", "Male",
            "Female", "Male", "Female"),
    value = c(44.5, 44.5, 6.6, 6.6, 7.24, 7.24, 72.9, 72.9),
    trait.order3 = c(1L, 1L, 2L, 2L, 3L, 3L, 4L, 4L),
    ind = structure(
      c(1L, 6L, 5L, 8L, 2L, 3L, 4L, 7L),
      .Label = c("ind=\n 182", "ind=\n 190", "ind=\n 195",
                 "ind=\n 200", "ind=\n 202", "ind=\n 305",
                 "ind=\n 309", "ind=\n 348"),
      class = "factor"
    )
  ),
  class = "data.frame",
  row.names = c(NA, 8L)
)

这里的技巧是使用 ind 变量作为您的 x 轴美学。为此,我建议对您的元数据 df2 和包含观察结果的原始 df1 使用连接。为了加入他们,我 'combined' trait.codeSex 并使用了 left_join.

#-- Add 'trait.comb' for join
df2 <- df2 %>%
    mutate(ind = str_remove(ind, "\n "),
           trait.comb = paste(trait.code, Sex, sep = "~")) %>%
    select(trait.comb, ind

#-- Add the information in df2 to df1 by joining using trait.comb
df1 <- df1 %>%
    mutate(trait.comb = paste(trait.code, Sex, sep = "~")) %>%
    left_join(df2, by = "trait.comb") %>%
    select(-trait.comb)

#-- Plot using the ind as your x-axis aesthetic
ggplot(df1, aes(ind, value)) +    
    facet_wrap(.~trait.code, nrow = 2, scales = "free") +    
    geom_boxplot(aes(fill = Sex), alpha = 0.2) + 
    theme_bw() +    
    theme(axis.title.y=element_blank(),
          legend.position="bottom", 
          panel.spacing.y = unit(2, "lines")) + 
    ggtitle("Any title")

回答原始问题:如果您使用 coord_cartesian(clip = "off") 关闭裁剪,geom_text() 可以在绘图面板外绘制。

ggplot(df1, aes(Sex, value)) +    
  geom_boxplot(aes(fill = Sex), alpha = 0.2) + 
  theme_bw() +    
  facet_wrap(.~trait.code, nrow = 2, scales = "free") +    
  geom_text(
    data = df2[df2$Sex == "Female",],
    aes(label = ind, y = -Inf), size = 4, vjust = 1.2, fontface="bold"
  ) +    
  geom_text(
    data = df2[df2$Sex == "Male",],
    aes(label = ind, y = -Inf), size = 4, vjust = 1.2, fontface="bold"
  ) +
  coord_cartesian(clip = "off") +
  theme(axis.title.x= element_blank(), 
        axis.title.y=element_blank(),
        legend.position="bottom",
        legend.box.spacing = unit(2, "lines"),
        axis.text.x = element_blank(), 
        panel.spacing.y = unit(2.5, "lines")) + 
  ggtitle("Any tittle")

reprex package (v0.3.0)

于 2019-11-16 创建