[英]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
如果我想添加有關每個 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
但是,我想改進我的代碼並找到另一種方法(如果存在的話)將每個信息放在下面給每個人 plot。
有誰知道可以做什么?
首先十分感謝
一般而言,plot 多面圖上的字幕:
如果你想要一個低於 allll plots的單個標題,你應該使用theme(plot.caption =...)
。
如果您希望在每個 facet 下方顯示相同的標題,您可以使用annotate()
並關閉剪裁。
如果您希望在每個 facet 下方顯示不同的標題,則需要能夠映射到數據集的內容(因此您可以為每個 facet 指定不同的文本)。 在這種情況下,我建議使用geom_text()
並進行一些巧妙的格式化以適合標題。
每個 plot 具有不同標題的替代方法是創建帶有標題的單獨圖,並通過grid.arrange()
或patchwork
或cowPlot()
將它們鏈接在一起......
這是使用geom_text()
和mtcars
的第三種情況的示例。 我希望您可以將其應用於您自己的數據集。
這是我們將用於添加標題的基本 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/13997761和https://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.