ggplot:将图块对齐在一起并添加常用标签和图例 [英] ggplot: align plots together and add common labels and legend

查看:1017
本文介绍了ggplot:将图块对齐在一起并添加常用标签和图例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 data.frame ,其中一个变量有许多级别(例如 param1 param2 param3 )。所有这些水平都有相同的单位(浓度mg L-1),但它们有不同的数值范围。

例如
$ b $从 0 0.4 > param1 / p>

param2 范围从 0 0.07



param3 范围从 0 3000



我不是使用data.frame,而是使用钻石创建一个可重现的例子

  library(dplyr)
library(ggplot2)
df < - 钻石%>%
dplyr :: filter(%c中的切割%(Fair,Ideal))%>%
dplyr :: filter(净度%in%c(I1,SI2,SI1,VS2,VS1,VVS2))%>%
dplyr :: mutate(new_price = ifelse(cut == 公平,
价格/ 100000,
价格/ 10))

正如 Fair 理想有不同的范围为了能够在y轴上分配断点,我为 Fair Ideal 创建了两个单独的图。 p>

我希望两个图中的两个轴具有相同的小数位数。我从这里使用 fmt_decimals()



顶部和底部的图不沿x轴。



我可以使用 ggarrange() egg

 库(蛋)
f_1 < - ggarrange(f1,f2)
f_1



现在这两幅图完全对齐。

QUESTIONS



code> gridExtra ?
如果不是
我可以使用 egg

以及如何添加常用的轴标签我能为这两个地块添加一个图例吗?

更新



感谢@ eipi10



我更新了如下

  library(cowplot)
#提取图例的函数
#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 )
传说< - tmp $ grobs [[leg]]
return(legend)}

#将图例提取为a grob
leg = g_legend(f1)

#从图中删除图例
f1 = f1 + theme(legend.position =none)
f2 = f2 + theme(legend.position =none)

#将两个
放在一起f_1 = plot_grid(f1,f2,ncol = 1,align =v)

f_3< - grid.arrange(
arrangeG rob(f_1,
bottom = grid :: textGrob(label = expression(Flow〜(m ^ {3}〜s ^ { - 1})),
gp = gpar(fontsize = 12,fontface =bold,col =black)),
left = grid :: textGrob(label = expression(Concentration〜mg〜L ^ { - 1}),rot = 90,
gp = gpar(fontsize = 12,fontface =bold,col =black))),
leg,
widths = c(9,1))

但似乎使用 cowplot ,在右边没有垂直的y线情节?



解决方案

我认为只要使用 ggplot2 就可以满足所有需求,包括共享x轴,共享轴标签和适当间距。对于我来说,看起来比用gtables更容易。



这是一个非常好的尝试:

  ggplot(df [df $ cut%in%c(Fair,Ideal),],aes(x = carat,y = new_price,color = color))+ 
geom_point(alpha = 0.3)+
scale_y_continuous(labels = fmt_dcimals(2))+
scale_x_continuous(limits = c(0,5.2),breaks = c(0,1,2,3,4, 5),labels = fmt_dcimals(2))+
facet_wrap(〜cut,scales ='free_y',nrow = 2)+
labs(x =,
y =)



如果您确实想要自定义休息时间,则可以使用休息功能来提供这些休息时间:

  make_breaks <  - 函数(范围){
if(范围[2]> 1){
c(0,250,500,750,1000,1250,1500,1750,2000)
} else {
c(0,0.05,0.1,0.15,0.2)


$ b $ ggplot(df [df $ cut%in%c(Fair,Ideal),],aes(x = carat,y = new_price ,color = color))+
geom_point(alpha = 0.3)+
scale_y_continuous(labels = fmt_dcimals(2),breaks = make_breaks)+
scale_x_continuous(limits = c(0,5.2) ,break = c(0,1,2,3,4,5),labels = fmt_dcimals(2))+
facet_wrap(〜cut,scales ='free_y',nrow = 2)+
实验室(x =,
y =)


I have a data.frame in which one variable has many levels (e.g. param1, param2and param3). All these levels have the same unit (concentration mg L-1) but they have different ranges of values.

For example

param1 ranges from 0 to 0.4

param2 ranges from 0 to 0.07

param3 ranges from 0 to 3000

Instead of using my data.frame, I used diamonds to create a reproducible example

library(dplyr)
library(ggplot2)
df <- diamonds %>%
  dplyr::filter(cut%in%c("Fair","Ideal")) %>%
  dplyr::filter(clarity%in%c("I1" ,  "SI2" , "SI1" , "VS2" , "VS1",  "VVS2")) %>%
  dplyr::mutate(new_price = ifelse(cut == "Fair", 
                                   price/100000, 
                                   price/10))

As Fair and Ideal have different ranges of values, I created two separate plots for Fair and Ideal to be able to assign the breaks in y axis

I want the two axes in the two plots to have the same number of decimals. I used fmt_decimals() from here.

library(dplyr)
library(ggplot2)
library(gridExtra)
library(grid)
#function to assign decimals for axes
fmt_dcimals <- function(decimals=0){
  function(x) format(x,nsmall = decimals,scientific = FALSE)
}


f1 <- 
 ggplot(df[df$cut == "Fair",], aes(x=carat , y= new_price, color = color))+
  geom_point(alpha = 0.3)+
  scale_y_continuous( limits = c(0,0.20), breaks=c(0, 0.05,0.1,0.15,0.2), labels = fmt_dcimals(2))+
  scale_x_continuous( limits = c(0,5.2), breaks=c(0,1,2,3,4,5), labels = fmt_dcimals(2))+
  facet_wrap(~cut) +
  labs(x = "",
       y = "")


f2 <- 
  ggplot(df[df$cut == "Ideal",], aes(x=carat , y= new_price, color = color))+
  geom_point(alpha = 0.3)+
  scale_y_continuous( limits = c(0,2000), breaks=c(0, 250,500,750,1000, 1250, 1500, 1750, 2000), labels = fmt_dcimals(2))+
  scale_x_continuous( limits = c(0,5.2), breaks=c(0,1,2,3,4,5), labels = fmt_dcimals(2))+
  facet_wrap(~cut) +
  labs(x = "",
       y = "")


f <- gridExtra::arrangeGrob(f1,f2, ncol=1, 
                            bottom=grid::textGrob(label= expression(Flow~(m^{3}~s^{-1})),
                                                  gp= gpar(fontsize=12, fontface="bold", col="black")),
                            left=grid::textGrob(label=expression(Concentration~mg~L^{-1}), rot=90, 
                                                gp= gpar(fontsize=12, fontface="bold", col="black")))

grid::grid.newpage() 
grid::grid.draw(f)

RESULT

The top and bottom plots are not aligned along x axis.

I can fix this using ggarrange() from egg package

library(egg)
f_1 <- ggarrange( f1, f2)
f_1

Now the two plots are perfectly aligned.

QUESTIONS

Any suggestions to align the two plots along x axis using gridExtra? If not Can I add common labels for axes using egg?

and how can I add only one legend for the two plots?

UPDATE

Thanks to @eipi10

I updated it as below

library(cowplot)
# 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(f1)

# Remove legend from plots
f1 = f1 + theme(legend.position = "none")
f2 = f2 + theme(legend.position = "none")

# Lay out the two
f_1 = plot_grid(f1, f2, ncol =1, align="v")

f_3 <- grid.arrange(
  arrangeGrob(f_1,  
              bottom=grid::textGrob(label= expression(Flow~(m^{3}~s^{-1})),
                                    gp= gpar(fontsize=12, fontface="bold", col="black")),
              left=grid::textGrob(label=expression(Concentration~mg~L^{-1}), rot=90, 
                                  gp= gpar(fontsize=12, fontface="bold", col="black"))),
  leg, 
  widths=c(9,1))

But it seems using cowplot, there is no vertical y line on the right side of the plot?

解决方案

I think you can everything you want using only ggplot2, including a shared x-axis, shared axis titels and proper spacing. To me that seems easier than messing around with gtables.

This is a perfectly fine attempt:

ggplot(df[df$cut %in% c("Fair", "Ideal"),], aes(x=carat , y= new_price, color = color))+
  geom_point(alpha = 0.3)+
  scale_y_continuous(labels = fmt_dcimals(2))+
  scale_x_continuous(limits = c(0,5.2), breaks=c(0,1,2,3,4,5), labels = fmt_dcimals(2))+
  facet_wrap(~cut, scales = 'free_y', nrow = 2) +
  labs(x = "",
       y = "")

If you really want to have custom breaks, you can use a break function to supply those:

make_breaks <- function(ranges) {
  if(ranges[2] > 1) {
    c(0, 250,500,750,1000, 1250, 1500, 1750, 2000)
  } else {
    c(0, 0.05,0.1,0.15,0.2)
  }
}

ggplot(df[df$cut %in% c("Fair", "Ideal"),], aes(x=carat , y= new_price, color = color))+
  geom_point(alpha = 0.3)+
  scale_y_continuous(labels = fmt_dcimals(2), breaks = make_breaks)+
  scale_x_continuous(limits = c(0,5.2), breaks=c(0,1,2,3,4,5), labels = fmt_dcimals(2))+
  facet_wrap(~cut, scales = 'free_y', nrow = 2) +
  labs(x = "",
       y = "")

这篇关于ggplot:将图块对齐在一起并添加常用标签和图例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆