【问题标题】:Avoid wasting space when placing multiple aligned plots onto one page将多个对齐的图放在一页上时避免浪费空间
【发布时间】:2012-10-25 18:05:36
【问题描述】:

我想在一个页面上放置四个图。轴标签应仅在最边缘打印,即 x 轴标签仅用于底部图表,y 轴标签仅用于左侧图表。这既适用于整个轴的名称,也适用于各个刻度线。我可以使用以下代码按照这些思路生成一些东西:

pdf(file = "ExampleOutput.pdf",
    width = 6.61,
    height = 6.61,
    pointsize = 10
    )
set.seed(42)
catA <- factor(c("m100", "m500", "m1000", "m2000", "m3000", "m5000"))
catB <- factor(20:28)
samples <- 100
rsample <- function(v) v[ceiling(runif(samples, max=length(v)))]
Tab <- data.frame(catA = rsample(catA),
                  catB = rsample(catB),
                  valA = rnorm(samples, 150, 8),
                  valB = pmin(1,pmax(0,rnorm(samples, 0.5, 0.3))))
par(mfrow = c(2,2))
for (i in 0:3) {
  x <- Tab[[1 + i %% 2]]
  plot(x, Tab[[3 + i %/% 2]],
       xlab = if (i %/% 2 == 1) "Some Categories" else NULL,
       ylab = if (i %% 2 == 0) "Some Values" else NULL,
       axes = FALSE
       )
  axis(side = 1,
       at=1:nlevels(x),
       labels = if (i %/% 2 == 1) levels(x) else FALSE)
  axis(side = 2, labels = (i %% 2 == 0))
  box(which = "plot", bty = "l")
}
par(mfrow = c(1,1))
dev.off()

我会欢迎有关如何改进我的绘图命令的建议,也许可以避免手动耗尽左下角的轴和 L。但这只是一个补充。

这个序列的结果如下所示:

这里的问题是大量浪费的空白。我的印象是 R 为轴和刻度标签保留空间,即使它们没有被使用。由于浪费了空间,对于左下角的图表,实际上只有每秒 x 个刻度被标记,这在这里真的很糟糕。

我想生成一个没有那么多空白的类似图。实际的地块应该是相同的大小,所以它们排列得当,但标签的空间应该只在外面。我想像这样的布局(在 GIMP 中创建的模型):

我怎样才能实现这样的布局?

【问题讨论】:

    标签: r plot


    【解决方案1】:

    假设 y 和 x 轴标签适用于所有图,这里对您显示的一般图进行了轻微修改。它使用外边距来包含轴标签,我们使用参数outer = TRUE 添加title()。效果有点像 ggplot2lattice 图中的标签。

    这里的关键是:

    op <- par(mfrow = c(2,2),
              oma = c(5,4,0,0) + 0.1,
              mar = c(0,0,1,1) + 0.1)
    

    设置绘图参数(调用之前的值存储在op)。我们在边 1 和边 2 上使用 54 线作为外边距,这是 mar 参数的常用数字。将各 1 行的绘图区域边距 (mar) 添加到顶部和右侧,以便在绘图之间留出一点空间。

    轴标签添加在for() 循环之后

    title(xlab = "Some Categories",
          ylab = "Some Values",
          outer = TRUE, line = 3)
    

    整个脚本是:

    set.seed(42)
    catA <- factor(c("m100", "m500", "m1000", "m2000", "m3000", "m5000"))
    catB <- factor(20:28)
    samples <- 100
    rsample <- function(v) v[ceiling(runif(samples, max=length(v)))]
    Tab <- data.frame(catA = rsample(catA),
                      catB = rsample(catB),
                      valA = rnorm(samples, 150, 8),
                      valB = pmin(1,pmax(0,rnorm(samples, 0.5, 0.3))))
    op <- par(mfrow = c(2,2),
              oma = c(5,4,0,0) + 0.1,
              mar = c(0,0,1,1) + 0.1)
    for (i in 0:3) {
      x <- Tab[[1 + i %% 2]]
      plot(x, Tab[[3 + i %/% 2]], axes = FALSE)
      axis(side = 1,
           at=1:nlevels(x),
           labels = if (i %/% 2 == 1) levels(x) else FALSE)
      axis(side = 2, labels = (i %% 2 == 0))
      box(which = "plot", bty = "l")
    }
    title(xlab = "Some Categories",
          ylab = "Some Values",
          outer = TRUE, line = 3)
    par(op)
    

    产生

    【讨论】:

    • 这很好,尽管它不能解决左下图 x 轴上标签的 OP 问题。轴标签上较小的点尺寸可能允许它们挤进去,但它可能会留下非常小的标签。
    • 好吧,我的例子选错了:两半的轴标签需要不同。尽管如此,很高兴知道这种方法确实存在,并且插图确实为答案增加了价值。而omamar 似乎无论如何都表明了一个有价值的方向。
    • 在这个答案的帮助下,我使用par(mfrow = c(2,2), oma = c(2, 2, 0, 0), mar = c(1, 1, 0, 0), mgp = c(2, 1, 0), xpd = NA) 让它为我工作。也请随意将其包含在您的答案中,非常感谢!
    • @Glen_b 我错过了答案中的那个具体点;明智地使用cex.axis 可以解决这个问题,就像使用las 旋转标签并在底部外边缘留出更多空间一样。
    【解决方案2】:

    the answer from Gavin Simpson 为基础,我现在使用以下解决方案:

    par(mfrow = c(2, 2),     # 2x2 layout
        oma = c(2, 2, 0, 0), # two rows of text at the outer left and bottom margin
        mar = c(1, 1, 0, 0), # space for one row of text at ticks and to separate plots
        mgp = c(2, 1, 0),    # axis label at 2 rows distance, tick labels at 1 row
        xpd = NA)            # allow content to protrude into outer margin (and beyond)
    

    结果如下:

    如您所见,这足以同时打印所有刻度标签。如果不是,那么根据Gavin's comment,将小于1的cex.axis添加到参数列表中应该有助于减小那里的字体大小。

    【讨论】:

      【解决方案3】:

      只需在par 中操作您的参数。参数mar 控制单个绘图的边距大小。将您的 par 更改为:

      par(mfrow = c(2,2), mar=c(1, 4, 1, 1) + 0.1)#it goes c(bottom, left, top, right) 
      

      【讨论】:

        【解决方案4】:

        您需要为par('mar') 分配适合定位的值的条件评估;这是检查“x-layout-position”的代码示例(在循环内):

            pdf(file = "ExampleOutput2.pdf",
            width = 6.61,
            height = 6.61,
            pointsize = 10
            )
        set.seed(42)
        catA <- factor(c("m100", "m500", "m1000", "m2000", "m3000", "m5000"))
        catB <- factor(20:28)
        samples <- 100
        rsample <- function(v) v[ceiling(runif(samples, max=length(v)))]
        Tab <- data.frame(catA = rsample(catA),
                          catB = rsample(catB),
                          valA = rnorm(samples, 150, 8),
                          valB = pmin(1,pmax(0,rnorm(samples, 0.5, 0.3))))
        par(mfrow = c(2,2), mar= c(3, 4, 1, 1) + 0.1)
        for (i in 0:3) {
          x <- Tab[[1 + i %% 2]]
          plot(x, Tab[[3 + i %/% 2]], mar= if(i %/%2 == 0) {c(4, 4, 1, 1) + 0.1 
                                                      }else{c(1, 1, 1, 1) + 0.1},
               xlab = if (i %/% 2 == 1) "Some Categories" else NULL,
               ylab = if (i %% 2 == 0) "Some Values" else NULL,
               axes = FALSE
               )
          axis(side = 1,
               at=1:nlevels(x),
               labels = if (i %/% 2 == 1) levels(x) else FALSE)
          axis(side = 2, labels = (i %% 2 == 0))
          box(which = "plot", bty = "l")
        }
        par(mfrow = c(1,1))
        dev.off()
        

        您需要调整它以满足您的需要,因为它只处理两个边距条件,并且您确实有 4 个单独的条件(下面两个都需要更多的底部空间,右边一个需要较少的左边空间,两个上面(也有不同的要求)。如果您在全局范围内缩小“mar”值,它将切断您的 x 和 y 标签,当您仅将此代码放入循环时,xlab 值的丢失可以看出。

        【讨论】:

        • 我试过了,我看不出结果有什么不同。难道是每个情节设置不适用于单个页面上多个情节的定位?还是有其他原因可能会抑制这种效果?你真的可以在我的代码中完成这项工作吗?
        • 它在您的代码中运行。但无论如何,加文的答案看起来更好。
        • 很奇怪,这对你有效,但对我无效。如果我有更多时间,我可能想进一步研究这一点,特别是因为您的解决方案可能对其他布局更灵活(例如,带有 some 内轴标记的 3x3)。但我今天不会追查这个。供参考:我尝试使用 R 2.15.2 并使用我的代码中指示的 pdf 输出驱动程序。
        • 好的,我将发布在带有 R 2.15.2 的 Mac 10.6.8 上工作的完整代码
        猜你喜欢
        • 2023-04-02
        • 1970-01-01
        • 2012-06-14
        • 2016-02-06
        • 1970-01-01
        • 2018-05-30
        • 2021-09-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多