首页 理论教育 使用R包gridExtra和cowplot合并多个独立图表

使用R包gridExtra和cowplot合并多个独立图表

时间:2023-11-19 理论教育 版权反馈
【摘要】:本节将介绍使用grid Extra、cowplot等R包合并多个独立图表的操作。这两个参数的长度由实际行数和列数决定。接下来我们学习cowplot包中的plot_grid函数,它不但可以自动对齐坐标轴,而且还会输出ggplot图表,方便我们添加其他元素并保存图表。

使用R包gridExtra和cowplot合并多个独立图表

本节将介绍使用grid Extra、cowplot等R包合并多个独立图表的操作。

一、grid.arrange

我们可以用grid Extra包中的grid.arrange方便地把多个并列图表合并起来。

# install.packages("grid Extra")

library(grid Extra)

library(ggplot2)

library(grid) # 使用grid.rectgrid.text

library(cowplot) # 使用ggdrawdraw_grobdraw_plotplot_grid

# 先生成多个独立图表

basic=ggplot()+geom_point(aes(1: 5, 1: 5))

# 修改背景的填充色和轮廓p1=basic+theme(plot.background=element_rect(fill="lightgreen", color="lightgreen"))

# 只修改背景填充色而不修改轮廓会导致图表周围有白边

p2=basic+theme(plot.background=element_rect(fill="lightgreen"))

# 设置coord_fixed()

p3=basic+coord_fixed()+theme(plot.background=element_rect (fill="lightgreen", color="lightgreen"))

# 当去掉背景和面板时整个图表的背景会显露出来

p4=basic+labs(y="Very Long Title")+theme(plot.background=element_blank(), panel.background=element_blank(), axis.title.y=element_text(angle=0, vjust=0.5))

## 用grid.arrange合并并调整放置方式

grid.arrange(p1, p2, p3) # 亦可用grobs=list(p1, p2, p3)的形式选择图表

# 像生成矩阵一样用nrow或ncol设置行数和列数

grid.arrange(p1, p2, p3, ncol=2)

# 以矩阵的形式明确放置方式并调整图表大小矩阵中的数字代表放置顺序NA代表不放置任何东西

pos=matrix(c(

1, 1, 1,

2, NA, NA), nrow=2, byrow=TRUE)

grid.arrange(p1, p2, layout_matrix=pos)

## 如果不希望每个子图表的面积相同可使用widths和heights调节大小这两个参数的值要么是用unit设置的绝对尺寸要么是相对数值例如widths= c(1, 3)表示第二列的宽度是第一列的三倍)。这两个参数的长度由实际行数和列数决定本例中的图表有两行两列所以此处要给出两个宽度值两个高度值

grid.arrange(p1, p2, p3, ncol=2, widths=c(1, 3), heights=unit(c(8,4), "cm"))

要强调的是,在保存由grid.arrange生成的图表时,我们必须明确为ggsave指定要保存的图表。

# 生成图表并赋值p=grid.arrange(...)

# 保存ggsave("文件名", plot=p)

grid包可用于为合并后的图表添加元素(我们已经在第五章介绍了用grid包添加文字和线条的方法)。

# 第一步用rect Grob函数添加矩形可用于修改整个图表的背景

bottom=rect Grob(gp=gpar(fill="khaki", col="khaki"))

# 第二步排列图表

p=grid.arrange(p1, p2, p3, p4, ncol=2)

# 第三步用text Grob添加文字

cha=text Grob(label="Combine Plots", x=0.5, y=0.5, gp=gpar (col="darkred", alpha=0.7, fontsize=30))

# 第四步合并我们先把图表的各部分放在列表中再用g List将它们合并以便生成可以保存的图表

final=do.call(g List, list(bottom, p, cha))

grid.newpage() # 使用grid包显示图表时需删除前边的图表

grid.draw(final) # 查看图表

# 保存ggsave("文件名", plot=final)

我们亦可使用cowplot包中的函数为合并后的图表添加背景。

## 方法一由于bottomp和cha均为grob对象所以可使用draw_grob函数添加

ggdraw()+draw_grob(bottom)+draw_grob(p)+draw_grob(cha)

## 方法二用ggplot添加背景和文字并用draw_plot添加

bottom_gg=ggplot()+theme_void()+

annotation_raster(matrix("khaki"), xmin=-Inf, xmax=Inf, ymin=Inf, ymax=Inf)

cha_gg=ggplot()+theme_void()+

geom_text(aes(0, 0, label="Combine Plots"), color="darkred", alpha=0.7, size=15)

ggdraw()+draw_plot(bottom_gg)+draw_grob(p)+draw_plot(cha_gg)

二、plot_grid

如果我们要确保各子图表的坐标轴自动对齐的话,可使用egg包中的ggarrange函数。它的使用方法和grid.arrange相似,读者可自行尝试。

接下来我们学习cowplot包中的plot_grid函数,它不但可以自动对齐坐标轴,而且还会输出ggplot图表,方便我们添加其他元素并保存图表。

# 排列图表时为了让p2和p4的纵坐标轴能够对齐我们使用了align参数它的选项为"none"默认不对齐)、"h"水平对齐)、"v"垂直对齐或"hv"两个方向都对齐)。在本例中p3没有跟其他图表对齐是因为它设置了coord_fixed()rel_widths和rel_heights用于指定相对宽度和相对高度

p=plot_grid(p1, p2, p3, p4, # 亦可写成plotlist=list(p1, p2, p3, p4)

ncol=2, align="v",

rel_widths=1, rel_heights=c(2, 1)

)

# 如不添加其他元素此处可直接用ggsave("文件名")保存

# 由于plot_grid生成的对象本身是一个ggplot图表所以我们只要往上添加图层即可注意由于ggdraw生成的图表坐标轴范围是从0至1所以为了把文字放在中间x和y均应设为0.5

ggdraw()+draw_plot(p)+geom_text(aes(x=0.5, y=0.5, label="Combine Plots"), color="darkred", alpha=0.7, size=20)

plot_grid还有两个跟坐标轴对齐有关的参数:

scale:子图表缩放比例。取值为单一数值,或者依次与每个图表相对应的多个数值。当其小于默认值1时,图表之间的缝隙会增大。显然,如果修改了缩放比例,图表之间就可能无法对齐了。

axis:在对齐子图表时,我们还可使用axis参数,它的取值为"t"、"b"、"l"、"r"(分别代表上、下、左、右),以及"tb"、"lr"(分别代表上下、左右)或"tblr"(四个方向同时对齐)。

三、多个图表共用一个图例

在多个并列图表使用相同图例的情况下,我们只须添加一个图例即可(图7-4-1)。

# install.packages("ggpubr")

library(ggpubr) # 使用get_legend

library(magick) # 用于读取图片

library(reshape2) # 使用melt

library(dplyr)

# 第一步绘制不带图例的图表

p1=ggplot()+geom_bar(show.legend=FALSE, aes(x=1: 5, y=1: 5, fill=factor(1: 5)), stat="identity")(www.xing528.com)

p2=ggplot()+geom_segment(show.legend=FALSE, aes(x=0, xend=5, y=1: 5, yend=1: 5, color=factor(1: 5)), size=2)

p3=ggplot()+geom_point(show.legend=FALSE, aes(1: 5, 1: 5, color=factor(1: 5)), size=5)

# 第二步任选一个带图例的图表并完成对图例的修改用ggpubr包中的get_legend函数提取图例的grob对象

p1_fake=ggplot()+geom_bar(aes(x=1: 5, y=1: 5, fill=factor(1: 5)), stat="identity")+

scale_fill_discrete(name="使用单一图例", guide=guide_legend(ncol=2)) leg=ggpubr::get_legend(p1_fake)

# 第三步把图例当成图表进行合并

grid.arrange(p1, p2, p3, leg, ncol=2)

当使用plot_grid时我们同样可使用上述方法添加图例我们以军费数据为例进行示范图7-4-1)。

图7-4-1 使用单一图例

dat=read.csv("military expd.csv", row.names=1) # 课件中的文件

dat=dat[, c(4, 5, 9)] # 只选取伊朗以色列和沙特阿拉伯的数据

# 整理数据

dat=round(dat/(10^6), 4) # 图表以百万美元为单位

dat=data.frame(dat, Year=as.numeric(rownames(dat)))

dat=melt(dat, id.vars="Year", measure.vars=c("Iran", "Israel","Saudi.Arabia"))

colnames(dat)=c("Year", "Country", "Value")

dat$Country=gsub("\\.", "\n", dat$Country)

# 计算增长率

dat=group_by(dat, Country)

increase_fun=function(x) c(NA, diff(x)/x[-length(x)]) # 注意增长率的第一个数字应是缺失值

dat=mutate(dat, Increase=increase_fun(Value))

dat=as.data.frame(dat)

# 第一步添加背景图片

img=image_read("jet.jpg") # 课件中的图片

bg=ggplot()+annotation_raster(img, xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf)+theme_void()

# 第二步绘制不带图例的图表

p1=ggplot(dat)+geom_line(show.legend=FALSE, aes(Year, Value, color=Country), size=1.1)+

geom_point(show.legend=FALSE, aes(Year, Value, color=Country), size=2.2)+

scale_color_manual(values=c("darkred", "coral", "khaki1"))+

scale_x_continuous(breaks=dat$Year)+

labs(title="MIlitary Expenditure (million current $)")

p2=ggplot(dat)+geom_line(show.legend=FALSE, na.rm=TRUE, aes(Year, Increase, color=Country), size=1.1)+

geom_point(show.legend=FALSE, na.rm=TRUE, aes(Year, Increase,color=Country), size=2.2)+

scale_color_manual(values=c("darkred", "coral", "khaki1"))+

scale_x_continuous(limits=range(dat$Year), breaks=dat$Year)+

labs(title="Increase Ratio (%)")

same_theme=theme_minimal(base_size=13, base_family="serif")+

theme(

axis.text.x=element_text(angle=20),

axis.title=element_blank(),

panel.grid.minor=element_blank(),

panel.grid.major=element_line(color="#133150"),

plot.background=element_rect(fill=scales::alpha("white", 0.3), color=NA)

)

p1=p1+same_theme

p2=p2+same_theme

p=plot_grid(p1, p2, ncol=1, align="v")

# 第三步生成带图例的图表并从中提取图例

leg=ggplot(dat)+

geom_line(na.rm=TRUE, aes(Year, Value, color=Country))+

scale_color_manual(values=c("darkred", "coral", "khaki1"), guide=guide_legend(override.aes=list(size=1.5)))+

theme_minimal(base_size=13, base_family="serif")+

theme(legend.background=element_rect(fill=scales::alpha("white", 0.5), color=NA))

leg=ggpubr::get_legend(leg)

# 第四步合并有时为防止使用draw_plot添加的图表交叠可以在它们占据的区域之间留出间隙

ggdraw()+draw_plot(bg)+draw_plot(p, x=0.025, y=0.025, width=0.7,height=0.95)+draw_grob(leg, x=0.8, width=0.2)

#==========

# 练习使用patchwork包

#==========

# patchwork包提供了涉及合并图表的更多操作以下示例对其功能进行了简单展示感兴趣的读者可以进一步学习

# install.packages("patchwork")

library(patchwork)

dat=data.frame(x=1: 3, y=1: 3)

p=ggplot(dat, aes(x, y))

p1=p+geom_point()

p2=p+geom_point(shape=15)

p3=p+geom_bar(stat="identity")

# 斜线表示上下并置竖线表示左右并置

(p1/p2)|p3

# 用plot_annotation为整个图表添加标题

((p1/p2)|p3)+plot_annotation(title="Title", subtitle="Subtitle", theme=theme(plot.title=element_text(color="blue"), plot. background=element_rect(fill="green")))

# 用加号把多个图表而不是多个图层连结起来用plot_spacer生成空白图表

p1+plot_spacer()+p2+p3+plot_layout(nrow=2, ncol=3, byrow=TRUE, width=c(2, 1, 2), height=c(2, 1))

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈