R,ggplot-共享相同y轴但x轴比例不同的图 [英] R, ggplot - Graphs sharing the same y-axis but with different x-axis scales

查看:180
本文介绍了R,ggplot-共享相同y轴但x轴比例不同的图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些数据集/变量,我想绘制它们,但我想以一种紧凑的方式做到这一点.为此,我希望他们共享相同的y轴,但要共享不同的x轴,并且由于分布不同,我希望其中一个x轴可以对数缩放,而另一个可以线性缩放.

I have some datasets/variables and I want to plot them, but I want to do this in a compact way. To do this I want them to share the same y-axis but distinct x-axis and, because of the different distributions, I want one of the x-axis to be log scaled and the other linear scaled.

假设我有一个长尾变量(我希望在绘制时对x轴进行对数缩放):

Suppose I have a long tailed variable (that I want the x-axis to be log-scaled when plotted):

library(PtProcess)
library(ggplot2)

set.seed(1)
lambda <- 1.5
a <- 1
pareto <- rpareto(1000,lambda=lambda,a=a)
x_pareto <- seq(from=min(pareto),to=max(pareto),length=1000)
y_pareto <- 1-ppareto(x_pareto,lambda,a)
df1 <- data.frame(x=x_pareto,cdf=y_pareto)

ggplot(df1,aes(x=x,y=cdf)) + geom_line() + scale_x_log10()

还有一个普通变量:

set.seed(1)
mean <- 3
norm <- rnorm(1000,mean=mean)
x_norm <- seq(from=min(norm),to=max(norm),length=1000)
y_norm <- pnorm(x_norm,mean=mean)
df2 <- data.frame(x=x_norm,cdf=y_norm)

ggplot(df2,aes(x=x,y=cdf)) + geom_line()

我想使用相同的y轴并排绘制它们.

I want to plot them side by side using the same y-axis.

我可以使用看起来不错的构面来执行此操作,但是我不知道如何使每个x轴具有不同的缩放比例(scale_x_log10()使它们的对数缩放):

I can do this with facets, which looks great, but I don't know how to make each x-axis with a different scale (scale_x_log10() makes both of them log scaled):

df1 <- cbind(df1,"pareto")
colnames(df1)[3] <- 'var'
df2 <- cbind(df2,"norm")
colnames(df2)[3] <- 'var'
df <- rbind(df1,df2)

ggplot(df,aes(x=x,y=cdf)) + geom_line() + 
       facet_wrap(~var,scales="free_x") + scale_x_log10()

使用grid.arrange,但我不知道如何使两个绘图区域保持相同的长宽比:

Use grid.arrange, but I don't know how to keep both plot areas with the same aspect ratio:

library(gridExtra)
p1 <- ggplot(df1,aes(x=x,y=cdf)) + geom_line() + scale_x_log10() +
      theme(plot.margin = unit(c(0,0,0,0), "lines"),
            plot.background = element_blank()) +
      ggtitle("pareto")
p2 <- ggplot(df2,aes(x=x,y=cdf)) + geom_line() + 
      theme(axis.text.y = element_blank(), 
            axis.ticks.y = element_blank(), 
            axis.title.y = element_blank(),
            plot.margin = unit(c(0,0,0,0), "lines"),
            plot.background = element_blank()) +
      ggtitle("norm")
grid.arrange(p1,p2,ncol=2)

PS:地块的数量可能会有所不同,所以我不是在寻找专门针对2个地块的答案

推荐答案

扩展尝试#2,gtable可能会帮助您.如果两个图表中的边距相同,则两个图中唯一改变的宽度(我认为)是y轴刻度标记标签和轴文本所占用的空间,从而改变了面板的宽度.使用此处中的代码,轴文本所占用的空间应相同,因此两个面板区域的宽度应相同相同,因此长宽比应相同.但是,结果(右边没有边距)看起来并不漂亮.因此,我在p2的右边添加了一点边距,然后在p2的左边删除了相同的量.同样对于p1:我在左侧添加了一点,但是在右侧添加了相同的金额.

Extending your attempt #2, gtable might be able to help you out. If the margins are the same in the two charts, then the only widths that change in the two plots (I think) are the spaces taken by the y-axis tick mark labels and axis text, which in turn changes the widths of the panels. Using code from here, the spaces taken by the axis text should be the same, thus the widths of the two panel areas should be the same, and thus the aspect ratios should be the same. However, the result (no margin to the right) does not look pretty. So I've added a little margin to the right of p2, then taken away the same amount to the left of p2. Similarly for p1: I've added a little to the left but taken away the same amount to the right.

library(PtProcess)
library(ggplot2)
library(gtable)
library(grid)
library(gridExtra)

set.seed(1)
lambda <- 1.5
a <- 1
pareto <- rpareto(1000,lambda=lambda,a=a)
x_pareto <- seq(from=min(pareto),to=max(pareto),length=1000)
y_pareto <- 1-ppareto(x_pareto,lambda,a)
df1 <- data.frame(x=x_pareto,cdf=y_pareto)

set.seed(1)
mean <- 3
norm <- rnorm(1000,mean=mean)
x_norm <- seq(from=min(norm),to=max(norm),length=1000)
y_norm <- pnorm(x_norm,mean=mean)
df2 <- data.frame(x=x_norm,cdf=y_norm)

p1 <- ggplot(df1,aes(x=x,y=cdf)) + geom_line() + scale_x_log10() +
      theme(plot.margin = unit(c(0,-.5,0,.5), "lines"),
            plot.background = element_blank()) +
      ggtitle("pareto")
p2 <- ggplot(df2,aes(x=x,y=cdf)) + geom_line() + 
      theme(axis.text.y = element_blank(), 
            axis.ticks.y = element_blank(), 
            axis.title.y = element_blank(),
            plot.margin = unit(c(0,1,0,-1), "lines"),
            plot.background = element_blank()) +
      ggtitle("norm")

gt1 <- ggplotGrob(p1)
gt2 <- ggplotGrob(p2)

newWidth = unit.pmax(gt1$widths[2:3], gt2$widths[2:3])

gt1$widths[2:3] = as.list(newWidth)
gt2$widths[2:3] = as.list(newWidth)

grid.arrange(gt1, gt2, ncol=2)

编辑 要在右侧添加第三个绘图,我们需要对绘图画布进行更多控制.一种解决方案是创建一个新的gtable,其中包含用于三个图的空间和一个用于右边界的附加空间.在这里,我让地块的边距照顾到地块之间的间距.

EDIT To add a third plot to the right, we need to take more control over the plotting canvas. One solution is to create a new gtable that contains space for the three plots and an additional space for a right margin. Here, I let the margins in the plots take care of the spacing between the plots.

p1 <- ggplot(df1,aes(x=x,y=cdf)) + geom_line() + scale_x_log10() +
      theme(plot.margin = unit(c(0,-2,0,0), "lines"),
            plot.background = element_blank()) +
      ggtitle("pareto")
p2 <- ggplot(df2,aes(x=x,y=cdf)) + geom_line() + 
      theme(axis.text.y = element_blank(), 
            axis.ticks.y = element_blank(), 
            axis.title.y = element_blank(),
            plot.margin = unit(c(0,-2,0,0), "lines"),
            plot.background = element_blank()) +
      ggtitle("norm")

gt1 <- ggplotGrob(p1)
gt2 <- ggplotGrob(p2)

newWidth = unit.pmax(gt1$widths[2:3], gt2$widths[2:3])

gt1$widths[2:3] = as.list(newWidth)
gt2$widths[2:3] = as.list(newWidth)

 # New gtable with space for the three plots plus a right-hand margin
gt = gtable(widths = unit(c(1, 1, 1, .3), "null"), height = unit(1, "null"))

# Instert gt1, gt2 and gt2 into the new gtable
gt <- gtable_add_grob(gt, gt1, 1, 1)
gt <- gtable_add_grob(gt, gt2, 1, 2)
gt <- gtable_add_grob(gt, gt2, 1, 3)

grid.newpage()
grid.draw(gt)

这篇关于R,ggplot-共享相同y轴但x轴比例不同的图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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