ggplot:如何将常用的x和y标签添加到图的网格中 [英] ggplot: how to add common x and y labels to a grid of plots
问题描述
使用钻石
,我想绘制克拉
vs 价格
4级( Fair ,
好,
很好
和 Premimum
) cut
。
不是让 facet_wrap()
来控制坐标轴中的断点,而是用四个图来控制断点在轴上。
库(ggplot2)
库(蛋)
库(网格)
f1< ; -
ggplot(diamonds [diamonds $ cut ==Fair,],aes(carat,price))+
geom_point()+
facet_wrap(〜cut,ncol = 2) +
scale_x_continuous(limits = c(0,4),breaks = c(0,1,2,3,4))+
scale_y_continuous(limits = c(0,10000),breaks = c (0,2500,5000,7500,10000))+
labs(x =表达式(),
y =表达式())
f2 < -
ggplot(diamonds [diamonds $ cut ==Good,],aes(carat,price))+
geom_point()+
facet_wrap(〜cut,ncol = 2)+
scale_y_continuous(limits = c(0,5000),breaks = c(0,1000,2000,3000,4000,5000))+
labs(x = expression(),
y = expression())
f3 < -
ggplot(diamonds [diamonds $ cut ==Very Good,],aes(carat ,价格))+
geom_point()+
facet_wrap(〜cut,ncol = 2)+
scale_x_continuous(limits = c(0,1),breaks = c(0,0.2, 0.4,0.6,0.8,1))+
scale_y_continuous(lim它= c(0,1000),break = c(0,200,400,600,800,1000))+
labs(x = expression(),
y = expression( ))
f4 < -
ggplot(diamonds [diamonds $ cut ==Premium,],aes(carat,price))+
geom_point()+ $ (限制= c(0,1.5),休息= c(0,0.2,0.4,0.6,0.8,1,1.2,1.4))+ b $ b facet_wrap(〜cut,ncol = 2)+
scale_x_continuous
scale_y_continuous(limits = c(0,3000),breaks = c(0,500,1000,1500,2000,2500,3000))+
labs(x = expression(),
y = expression())
fin_fig < - ggarrange(f1,f2,f3,f4,ncol = 2)
fin_fig
结果
不同y值的范围
问题
在所有方面,x和y轴是s AME。唯一的区别是最小,最大和休息。我想为此图添加x和y标签。我可以在任何文档或图像编辑器中手动执行此操作。有没有办法直接在R中完成它?
除了使用 gridExtra
包(根据@ user20650的建议),您还可以通过将钻石
数据框分为 cut
并使用 mapply
。
下面的答案还包括评论中后续问题的解决方案。我们展示了如何布置四个地块,添加适用于所有地块的单个x和y标签(包括使其变为粗体并控制其颜色和大小),并为每个地块获取单个图例而不是单独的图例。 / b>
库(ggplot2)
库(gridExtra)
库(网格)
库)
删除 cut
为理想
:
dat = diamonds [diamonds $ cut!=Ideal ,]
dat $ cut = droplevels(dat $ cut)
创建四张图,一个用于 mapply
(而不是 lapply
),这样我们可以为<$ c的每个级别提供单独的数据框$ c> cut 和一个自定义 ymax
值的矢量,以分别为每个绘图设置y轴上的最高值。我们还添加了 color = clarity
以创建一个颜色图例:
pl = mapply(FUN = function(df,ymax){
ggplot(df,aes(carat,price,color = clarity))+
geom_point()+
facet_wrap ,ncol = 2)+
scale_x_continuous(limits = c(0,4),breaks = 0:4)+
scale_y_continuous(limits = c(0,ymax),labels = dollar_format())+
labs(x = expression(),
y = expression())
},df = split(dat,dat $ cut),ymax = c(1e4,5e3, 1e3,3e3),SIMPLIFY = FALSE)
好的,我们有四个地块,但每个地块都有它自己的传奇。所以现在我们要安排只有一个整体图例。我们通过提取其中一个图例作为单独的grob( gr aphical ob 项目),然后从四个图中删除图例来完成此操作。
使用小帮助函数将图例解压为单独的grob:
#提取图例的函数
#https://github.com/hadley/ggplot2/wiki/Share-a-legend-between-two-ggplot2-graphs
g_legend< -function(a.gplot){
tmp< - ggplot_gtable(ggplot_build(a.gplot))
leg< - 其中(sapply(tmp $ grobs,function(x)x $ name)==guide-box)
legend < - tmp $ grobs [[leg]]
return(legend)}
#将图例提取为grob
leg = g_legend(pl [[1]])
现在我们需要将这四个图放置在2x2网格中,然后将图例放在此图的右侧格。我们使用> arrangeGrob
来绘制图表(并注意我们如何使用 lapply
从渲染前的每个绘图中移除图例它)。这与本答案的早期版本中 grid.arrange
所做的基本相同,除了 arrangeGrob
创建2x2阴谋网格对象而不绘制它。然后我们通过在 grid.arrange
中包装整个事物,在2x2阴谋网格旁边布置图例。 widths = c(9,1)
将水平空间的90%分配给图的2×2网格和10%的图例。 Whew!
grid.arrange(
arrangeGrob(grobs = lapply(pl,function(p)p + guides color = FALSE)),ncol = 2,
bottom = textGrob(Carat,gp = gpar(fontface =bold,col =red,fontsize = 15)),
left = textGrob(Price,gp = gpar(fontface =bold,col =blue,fontsize = 15),rot = 90)),
leg,
widths = c(9,1 )
)
Using diamonds
, I want to plot carat
vs price
for 4 levels (Fair
, Good
, Very Good
and Premimum
) of cut
.
Instead of allowing facet_wrap()
to control the breaks in the axes, I made four plots to control the breaks in axes.
library(ggplot2)
library(egg)
library(grid)
f1 <-
ggplot(diamonds[diamonds$cut=="Fair",], aes(carat, price))+
geom_point()+
facet_wrap(~cut, ncol =2)+
scale_x_continuous(limits = c(0,4), breaks=c(0, 1, 2, 3, 4))+
scale_y_continuous(limits = c(0,10000), breaks=c(0, 2500, 5000, 7500, 10000))+
labs(x=expression(" "),
y=expression(" "))
f2 <-
ggplot(diamonds[diamonds$cut=="Good",], aes(carat, price))+
geom_point()+
facet_wrap(~cut, ncol =2)+
scale_y_continuous(limits = c(0,5000), breaks=c(0, 1000, 2000, 3000, 4000, 5000))+
labs(x=expression(" "),
y=expression(" "))
f3 <-
ggplot(diamonds[diamonds$cut=="Very Good",], aes(carat, price))+
geom_point()+
facet_wrap(~cut, ncol =2)+
scale_x_continuous(limits = c(0,1), breaks=c(0, 0.2, 0.4, 0.6, 0.8, 1))+
scale_y_continuous(limits = c(0,1000), breaks=c(0, 200, 400, 600, 800, 1000))+
labs(x=expression(" "),
y=expression(" "))
f4 <-
ggplot(diamonds[diamonds$cut=="Premium",], aes(carat, price))+
geom_point()+
facet_wrap(~cut, ncol =2)+
scale_x_continuous(limits = c(0,1.5), breaks=c(0, 0.2, 0.4, 0.6, 0.8, 1, 1.2, 1.4))+
scale_y_continuous(limits = c(0, 3000), breaks=c(0, 500, 1000, 1500, 2000, 2500, 3000))+
labs(x=expression(" "),
y=expression(" "))
fin_fig <- ggarrange(f1, f2, f3, f4, ncol =2)
fin_fig
RESULT
Each plot has a range of different y values
QUESTION
In all facets, x and y axes are the same. The only difference is the min, max and the breaks. I want to add x and y labels to this figure. I can do this manually in any word document or image editor. Is there anyway to do it in R directly?
In addition to using functions from the gridExtra
package (as suggested by @user20650), you can also create your plots with less code by splitting the diamonds
data frame by levels of cut
and using mapply
.
The answer below also includes solutions for follow-up questions in the comments. We show how to lay out the four plots, add single x and y labels (including making them bold and controlling their color and size) that apply to all the plots, and get a single legend rather than a separate legend for each plot.
library(ggplot2)
library(gridExtra)
library(grid)
library(scales)
Remove rows where cut
is "Ideal"
:
dat = diamonds[diamonds$cut != "Ideal",]
dat$cut = droplevels(dat$cut)
Create four plots, one for each remaining level of cut
and store in a list. We use mapply
(instead of lapply
) so that we can provide both separate data frames for each level of cut
and a vector of custom ymax
values to set the highest value on the y-axis separately for each plot. We also add color=clarity
in order to create a color legend:
pl = mapply(FUN = function(df, ymax) {
ggplot(df, aes(carat, price, color=clarity))+
geom_point()+
facet_wrap(~cut, ncol=2)+
scale_x_continuous(limits = c(0,4), breaks=0:4)+
scale_y_continuous(limits = c(0, ymax), labels=dollar_format()) +
labs(x=expression(" "),
y=expression(" "))
}, df=split(dat, dat$cut), ymax=c(1e4,5e3,1e3,3e3), SIMPLIFY=FALSE)
Okay, we have our four plots, but each one has its own legend. So now we want to arrange to have only one overall legend. We do this by extracting one of the legends as a separate grob (graphical object) and then removing the legends from the four plots.
Extract the legend as a separate grob using a small helper function:
# Function to extract legend
# https://github.com/hadley/ggplot2/wiki/Share-a-legend-between-two-ggplot2-graphs
g_legend<-function(a.gplot){
tmp <- ggplot_gtable(ggplot_build(a.gplot))
leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
legend <- tmp$grobs[[leg]]
return(legend) }
# Extract legend as a grob
leg = g_legend(pl[[1]])
Now we need to arrange the four plots in a 2x2 grid and then place the legend to the right of this grid. We use arrangeGrob
to lay out the plots (and note how we use lapply
to remove the legend from each plot before rendering it). This is essentially the same as what we did with grid.arrange
in an earlier version of this answer, except that arrangeGrob
creates the 2x2 plot grid object without drawing it. Then we lay out the legend beside the 2x2 plot grid by wrapping the whole thing inside grid.arrange
. widths=c(9,1)
allocates 90% of the horizontal space to the 2x2 grid of plots and 10% to the legend. Whew!
grid.arrange(
arrangeGrob(grobs=lapply(pl, function(p) p + guides(colour=FALSE)), ncol=2,
bottom=textGrob("Carat", gp=gpar(fontface="bold", col="red", fontsize=15)),
left=textGrob("Price", gp=gpar(fontface="bold", col="blue", fontsize=15), rot=90)),
leg,
widths=c(9,1)
)
这篇关于ggplot:如何将常用的x和y标签添加到图的网格中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!