在R中创建具有相同轴的多个散点图

时间:2013-02-15 22:55:02

标签: r graphics plot rpy2

我正在尝试在R中以2 x 2排列绘制四个散点图(我实际上是通过rpy2绘图)。我希望每个都具有1的纵横比,但也是相同的比例,所以所有子图的相同的X和Y标记,以便它们可以进行比较。我尝试使用par

执行此操作
par(mfrow=c(2,2))
# scatter 1
plot(x, y, "p", asp=1)
# scatter 2
plot(a, b, "p", asp=1)
# ...

修改:

这是我现在所拥有的直接例子:

> par(mfrow=c(2,2))
> for (n in 1:4) { plot(iris$Petal.Width, rnorm(length(iris$Petal.Width)), "p", asp=1) }

可以创建正确的散射类型,但具有不同的比例。将ylimxlim设置为在上方plot的每次调用中都相同,并不会解决问题。您仍然会在每个轴上获得非常不同的刻度线和刻度数,这使得分散不必要地难以解释。我希望X和Y轴相同。例如,这个:

for (n in 1:4) { plot(iris$Petal.Width, rnorm(length(iris$Petal.Width)), "p", asp=1, xlim=c(-4, 6), ylim=c(-2, 4)) }

生成错误的结果:

enter image description here

确保在所有子图中使用相同轴的最佳方法是什么?

我正在寻找的是像axis=same这样的参数或类似于par(mfrow=...)的参数,这听起来像lattice的默认行为,使轴在每个轴上共享和相同副区。

lgautier用ggplot给出了很好的代码,但它要求提前知道轴。我想澄清一点,我想避免遍历每个子图中的数据并自己计算要绘制的正确刻度。如果必须提前知道,那么ggplot解决方案要比仅使用plot和明确

绘图复杂得多

agstudy给出了格子的解决方案。这看起来与我想要的最接近,因为你不必明确预先计算每个散点的刻度位置,但作为新用户,我无法弄清楚如何使格子看起来像普通的情节。我得到的最接近的是:

> xyplot(y~x|group, data =dat, type='p',
        between =list(y=2,x=2),
        layout=c(2,2), aspect=1,
               scales =list(y = list(relation='same'), alternating=FALSE))

产生:

enter image description here

我怎样才能让它看起来像R基座?我不希望在每个子图的顶部有这些group字幕,或者在每个散点的顶部和右边没有标记的刻度,我只想要标记散射的每个x和y。我也不是在寻找X和Y的共享标签 - 每个子图都有自己的X和Y标签。并且每个散点中的轴标签必须相同,尽管这里选择的数据没有意义。

除非有一种简单的方法让格子看起来像R基座,听起来好像答案是没有办法做我想在R里做的事(令人惊讶),没有预先计算每个蜱的确切位置在每个子图中,这需要提前迭代数据。

3 个答案:

答案 0 :(得分:3)

使用latticeggplot2您需要重塑数据。例如:

  1. 创建4个data.frame(x = x1,y = y1)...
  2. 为每个data.frame,group = 1,2,...
  3. 添加一个组列
  4. 一次性修改4个data.frame
  5. 这是使用lattice

    的示例
    dat <- data.frame(x = rep(sample(1:100,size=10),4),
                      y = rep(rnorm(40)),
                      group = rep(1:4,each =10))
    
    xyplot(y~x|group,       ## conditional formula to get 4 panels
           data =dat,       ## data
           type='l',        ## line type for plot
           groups=group,     ## group ti get differents colors
           layout=c(2,2))   ## equivalent to par or layout
    

    enter image description here

    PS:不需要设置圣诞节。在xyplot中,默认的骶骨设置为same(所有面板的骶骨相同)。您可以修改它,例如:

    xyplot(y~x|group, data =dat, type='l',groups=group,
           layout=c(2,2), scales =list(y = list(relation='free')))
    

    修改

    格子绘图有很多参数 函数允许控制绘图的许多细节,例如我自定义:

    1. 用于条带标签和标题的文字
    2. 轴刻度标签的大小和位置,
    3. 列和行之间的间隙大小。

      xyplot(y~x|group, data =dat, type='l',groups=group,
            between =list(y=2,x=2),
            layout=c(2,2), 
            strip = myStrip,
            scales =list(y = list(relation='same',alternating= c(3,3))))
      
    4. 其中

      myStrip <- function(var.name,which.panel, which.given,...) {
        var.name <- paste(var.name ,which.panel)
        strip.default(which.given,which.panel,var.name,...)
        }
      

      enter image description here

      编辑为了获得格子图基本图形图,您可以试试这个:

      xyplot(y~x|group, data =dat, type='l',groups=group,
             between=list(y=2,x=2),
             layout=c(2,2), 
             strip =FALSE,
             xlab=c('a','a'),
             xlab.top=c('a','a'),
             ylab=c('b','b'),
             ylab.right = c('b','b'),
             main=c('plot1','plot2'),
             sub=c('plot3','plot4'),
             scales =list(y = list(alternating= c(3,3)),
                          x = list(alternating= c(3,3))))
      

      enter image description here

答案 1 :(得分:3)

如果开始,

ggplot2可能具有最高的漂亮/宽松比率。

rpy2示例:

from rpy2.robjects.lib import ggplot2
from rpy2.robjects import r, Formula

iris = r('iris')

p = ggplot2.ggplot(iris) + \
    ggplot2.geom_point(ggplot2.aes_string(x="Sepal.Length", y="Sepal.Width")) + \
    ggplot2.facet_wrap(Formula('~ Species'), ncol=2, nrow = 2) + \
    ggplot2.GBaseObject(r('ggplot2::coord_fixed')()) # aspect ratio
# coord_fixed() missing from the interface, 
# therefore the hack. This should be fixed in rpy2-2.3.3

p.plot()

将评论读到之前的答案我看到你可能意味着完全分开 地块。使用R的默认绘图系统,par(mfrow(c(2,2))par(mfcol(c(2,2)))是最简单的方法,并保持纵横比,轴的范围和刻度线通过固定的常规方式保持一致。

在R中绘制的最灵活的系统可能是grid。它没有看起来那么糟糕,可以想象是一个场景图。使用rpy2,ggplot2和grid:

from rpy2.robjects.vectors import FloatVector

from rpy2.robjects.lib import grid
grid.newpage()
lt = grid.layout(2,2) # 2x2 layout
vp = grid.viewport(layout = lt)
vp.push()


# limits for axes and tickmarks have to be known or computed beforehand
xlims = FloatVector((4, 9))
xbreaks = FloatVector((4,6,8))
ylims = FloatVector((-3, 3))
ybreaks = FloatVector((-2, 0, 2))

# first panel
vp_p = grid.viewport(**{'layout.pos.col':1, 'layout.pos.row': 1})
p = ggplot2.ggplot(iris) + \
    ggplot2.geom_point(ggplot2.aes_string(x="Sepal.Length",
                                          y="rnorm(nrow(iris))")) + \
    ggplot2.GBaseObject(r('ggplot2::coord_fixed')()) + \
    ggplot2.scale_x_continuous(limits = xlims, breaks = xbreaks) + \
    ggplot2.scale_y_continuous(limits = ylims, breaks = ybreaks)
p.plot(vp = vp_p)
# third panel
vp_p = grid.viewport(**{'layout.pos.col':2, 'layout.pos.row': 2})
p = ggplot2.ggplot(iris) + \
    ggplot2.geom_point(ggplot2.aes_string(x="Sepal.Length",
                                          y="rnorm(nrow(iris))")) + \
    ggplot2.GBaseObject(r('ggplot2::coord_fixed')()) + \
    ggplot2.scale_x_continuous(limits = xlims, breaks = xbreaks) + \
    ggplot2.scale_y_continuous(limits = ylims, breaks = ybreaks)
p.plot(vp = vp_p)

rpy2 documentation about graphics中的更多文档,以及ggplot2和网格文档中的更多文档。

答案 2 :(得分:2)

虽然已经选择了答案,但该答案使用ggplot而不是基础R,这是OP想要的。虽然ggplot非常适合快速绘图,但对于出版物而言,您通常希望更好地控制绘图而不是ggplot。这就是基础情节优秀的地方。

我建议您阅读Sean Anderson's explanation可以通过巧妙使用par来实现的魔法,以及其他一些好用的技巧,例如使用layout()split.screen()

用他的解释,我想出了这个:

# Assume that you are starting with some data, 
# rather than generating it on the fly
data_mat <- matrix(rnorm(600), nrow=4, ncol=150)
x_val <- iris$Petal.Width

Ylim <- c(-3, 3)
Xlim <- c(0, 2.5)

# You'll need to make the ylimits the same if you want to share axes


par(mfrow=c(2,2))
par(mar=c(0,0,0,0), oma=c(4,4,0.5,0.5))
par(mgp=c(1, 0.6, 0.5))
for (n in 1:4) { 
  plot(x_val, data_mat[n,], "p", asp=1, axes=FALSE, ylim=Ylim, xlim=Xlim)
  box()
  if(n %in% c(1,3)){
    axis(2, at=seq(Ylim[1]+0.5, Ylim[2]-0.5, by=0.5))
  }
  if(n %in% c(3,4)){
    axis(1, at=seq(min(x_val), max(x_val), by=0.1))
  }
}

Plot with shared margins

这里还有一些工作要做。就像在OP中一样,数据似乎在中间被压扁了。当然,调整事物会很好,因此可以使用完整的绘图区域。