5

我试图在 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) }

它创建了正确类型的散点图,但具有不同的比例。在上面的每次调用中设置ylim和相同不能解决问题。您仍然会在每个轴上看到非常不同的刻度线和刻度数,这使得散布图难以解释。我希望 X 轴和 Y 轴相同。例如,这个:xlimplot

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)) }

生成错误的结果:

在此处输入图像描述

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

我所寻找的只是一个axis=same类似于 to的参数par(mfrow=...),这听起来像是 的默认行为lattice,以使轴在每个子图中共享且相同。

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

agstudy 给出了一个带有 lattice 的解决方案。这看起来最接近我想要的,因为您不必显式地预先计算每个散点的刻度位置,但是作为一个新用户,我无法弄清楚如何使格子看起来像一个普通的图。我得到的最接近的是:

> 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))

产生:

在此处输入图像描述

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

除非有一种简单的方法可以使格子看起来像 R 基础,否则听起来答案是没有办法做我在 R 中尝试做的事情(令人惊讶),而不预先计算每个子图中每个刻度的确切位置,这需要提前遍历数据。

4

3 回答 3

3

和你需要重塑数据latticeggplot2例如:

  1. 创建 4 个 data.frame(x=x1,y=y1)...
  2. 为每个 data.frame 添加一个 group 列,group=1,2,...
  3. 一次rbind 4个data.frame

这是一个使用示例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

在此处输入图像描述

PS:不需要设置sacles。在xyplot默认的 sacles 设置中是same(所有面板都使用相同的 sacles)。您可以修改它,例如:

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))))
    

在哪里

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

在此处输入图像描述

编辑为了得到一个格子图基础图形图,你可以试试这个:

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))))

在此处输入图像描述

于 2013-02-15T23:50:40.293 回答
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 和网格:

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 文档中有关 graphics的更多文档,以及 ggplot2 和网格文档中的更多文档。

于 2013-02-16T07:46:56.943 回答
2

尽管已经选择了一个答案,但该答案使用ggplot而不是基数 R,这正是 OP 想要的。虽然ggplot非常适合快速绘图,但对于发布,您通常希望对绘图进行更好的控制而不是ggplot提供。这就是基础情节擅长的地方。

我建议阅读Sean Anderson 对可以巧妙使用 的魔法的解释par,以及其他一些不错的技巧,例如使用layout()and 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))
  }
}

具有共享边距的绘图

这里还有一些工作要做。就像在 OP 中一样,数据在中间出现挤压。当然,调整一些东西以便使用完整的绘图区域会很好。

于 2014-09-10T20:15:15.647 回答