簡體   English   中英

如何在 R 中使用 facet_grid 在每個人 plot 中添加字幕?

[英]How to add captions in each individual plot using facet_grid in R?

我正在使用facet_grid繪制多個圖,我想知道如何在每個 plot 中添加一些額外信息作為標題。

我設法在每個 plot 的標題中添加信息(以添加 Kruskal-Wallis p 值),但我想在每個 plot 下方添加更多信息(作為標題)。

這是一個可重現的例子:

library(ggplot2)
library(dplyr)
set.seed(1234)
Gene <- floor(runif(25, min=0, max=101))
Age <- floor(runif(25, min=18, max=75))
Group <- c("Group1", "Group1", "Group3", "Group2", "Group1", "Group3", "Group2", "Group2", "Group2", "Group1", "Group1", "Group3", "Group1", "Group2", "Group1", "Group2", "Group3", "Group1", "Group3", "Group3", "Group2", "Group1", "Group3", "Group3","Group2")


df <- data.frame(Gene, Age, Group)
df$Group <- as.factor(df$Group)

mybreaks <- seq(min(df$Age)-1, to=max(df$Age)+10, by=10)
df$groups_age <- cut(df$Age, breaks = mybreaks, by=10)

bp <- ggplot(df, aes(x=groups_age, y=Gene, group=groups_age)) + 
  geom_boxplot(aes(fill=groups_age)) + 
  facet_grid(. ~ Group)

bp

pval <- df %>%
  group_by(Group) %>%
  summarize(Kruskal_pvalue = kruskal.test(Gene ~ groups_age)$p.value)

# This is to create new labels for the facetgrid where we can show the phenotype and the KW pvalue.
labels <- c(paste('Group 1\n KW p-val:', signif(subset(pval$Kruskal_pvalue, pval$Group=="Group1"), digits = 3)),
            paste('Group 2\n  KW p-val:', signif(subset(pval$Kruskal_pvalue, pval$Group=="Group2"), digits = 3)),
            paste('Group 3\n  KW p-val:', signif(subset(pval$Kruskal_pvalue, pval$Group=="Group3"), digits = 3)))

df$KW <- factor(df$Group, levels = levels(df$Group), labels = labels)


bp <- ggplot(df, aes(x=groups_age, y=Gene, group=groups_age)) + 
  geom_boxplot(aes(fill=groups_age)) + 
  facet_grid(. ~ KW) +
  theme(legend.position="none")
bp

這是上面代碼的結果: 圖片 1

如果我想添加有關每個 plot 的信息作為標題,這是我能想到的唯一方法。

df_group1 <- df[df$Group == "Group1",]
df_group2 <- df[df$Group == "Group2",]
df_group3 <- df[df$Group == "Group3",]

myfunction <- function(DF){
  df <- as.data.frame(table(DF$groups_age))
  # This is to add  ": n = " to the first column
  df$Var1 <- paste(df$Var1, ": n = ", sep = "")
  # We join both columns in one to have the result together.
  df$X <- paste(df$Var1, df$Freq)
  # We save that column into a variable 
  vec <-  df[["X"]]
  return(vec)
}

numb_group1 <- myfunction(df_group1)
numb_group1 <- paste(numb_group1, collapse = "; ") 

numb_group2 <- myfunction(df_group2)
numb_group2 <- paste(numb_group2, collapse = "; ") 

numb_group3 <- myfunction(df_group3)
numb_group3 <- paste(numb_group3, collapse = "; ") 

numb_all <- c(numb_group1, numb_group2, numb_group3)


bp <- bp + labs(caption = paste0("Group 1: n = ", nrow(subset(df, df$Group=="Group1")), 
                                 "\n", 
                                 "           Groups: ", numb_all[1],
                                 "\n",
                                 "\n",
                                 "Group 2: n = ", nrow(subset(df, df$Group=="Group2")), 
                                 "\n",
                                 "           Groups: ", numb_all[2],
                                 "\n",
                                 "\n",
                                 "Group 3: n = ", nrow(subset(df, df$Group=="Group3")), 
                                 "\n",
                                 "           Groups:", numb_all[3]
)) +  theme(legend.position="none",
            plot.caption = element_text(hjust = 0, face= "italic")) #Default is hjust=1
bp

這是它的樣子: 圖 2

但是,我想改進我的代碼並找到另一種方法(如果存在的話)將每個信息放在下面給每個人 plot。

有誰知道可以做什么?

首先十分感謝

一般而言,plot 多面圖上的字幕:

  • 如果你想要一個低於 allll plots單個標題,你應該使用theme(plot.caption =...)

  • 如果您希望在每個 facet 下方顯示相同的標題,您可以使用annotate()並關閉剪裁。

  • 如果您希望在每個 facet 下方顯示不同的標題,則需要能夠映射到數據集的內容(因此您可以為每個 facet 指定不同的文本)。 在這種情況下,我建議使用geom_text()並進行一些巧妙的格式化以適合標題。

  • 每個 plot 具有不同標題的替代方法是創建帶有標題的單獨圖,並通過grid.arrange()patchworkcowPlot()將它們鏈接在一起......

這是使用geom_text()mtcars的第三種情況的示例。 我希望您可以將其應用於您自己的數據集。

基本 plot

這是我們將用於添加標題的基本 plot:

library(ggplot2)
p <- ggplot(mtcars, aes(qsec, mpg)) + geom_point() +
        facet_wrap(~cyl)

在此處輸入圖像描述

標題數據框

要制作標題 plot,我們首先需要定義每個方面的文本。 最好在與批量數據不同的數據框中執行此操作。 這確保了文本 geom 沒有任何過度繪圖(在同一位置多次繪制),因為在 data frame 中的每個觀察都繪制了一個文本 geom 這是我們的 dataframe 的字幕:

caption_df <- data.frame(
  cyl = c(4,6,8),
  txt = c("carb=4", "carb=6", "carb=8, OMG!")
)

帶字幕的繪圖

要制作 plot,我們需要對 plot 進行一些調整。

  • 添加標題。 geom_text()和 map 添加到caption_df 我們將 map 文本,但 position 將固定在 x 和 y。 x 值設置為原始數據的最小值,但我們也可以手動設置。 y 值需要設置為低於原始 plot的值。

  • 限制 plot 的限制。 由於我們將文本幾何放置在原始 plot 區域下方,如果我們不限制 plot 區域的范圍, ggplot2只會擴展新的文本范圍。 我們需要保持原來的 y 限制,以確保我們添加的geom_text()的 y 值保持該區域以下。

  • 關閉剪輯。 為了真正看到新的字幕,您需要關閉剪輯。 您可以在任何coord_*()函數中執行此操作,因此我們將使用coord_cartesian()執行此操作並設置 y 限制。

  • 增加下限。 為了確保我們在最終圖像中看到標題,我們需要通過theme(plot.margin=...)增加 plot 下方的邊距。

這是所有這一切的最終結果。

ggplot(mtcars, aes(qsec, mpg)) + geom_point() + facet_wrap(~cyl) +
  coord_cartesian(clip="off", ylim=c(10, 40)) +
  geom_text(
    data=caption_df, y=5, x=min(mtcars$qsec),
    mapping=aes(label=txt), hjust=0,
    fontface="italic", color="red"
  ) +
  theme(plot.margin = margin(b=25))

在此處輸入圖像描述

在使用facet_grid和標題嘗試了很多事情之后,我創建了一些帖子,在那里我得到了非常好的答案,可以幫助解決這個問題的人。

這是主要的解決方案: https://stackoverflow.com/a/71557785/13997761

雖然這在我嘗試自動化代碼時給我帶來了一些問題: https://stackoverflow.com/a/71561745/13997761https://stackoverflow.com/a/71569950/13997761

但是,我意識到對於這種情況,最好將觀察值的數量放在每個箱線圖上方。 它更直觀,不需要很多代碼。

myFreqs <- df %>%  
  group_by(Group, groups_age) %>% 
  summarise(Freq = n()) 
myFreqs 


bp + stat_summary(geom = 'text', label = paste("n = ", myFreqs$Freq), fun = max, vjust = -1, position = position_dodge(width=0.7))

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM