我想将四个地块放在一个页面上。轴标签应仅在最边缘打印,即仅用于底部图的 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中创建的模型):
我如何实现这样的布局?
答案 0 :(得分:57)
这是对您显示的一般图的略微修改,假设y轴和x轴标签属于所有图。它使用外边距来包含轴标记,我们使用参数title()
添加outer = TRUE
。效果有点像 ggplot2 或晶格图中的标记。
这里的关键是:
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边使用5
和4
行作为外边距,这是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)
产生
答案 1 :(得分:19)
严重依赖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
应该有助于减少那里的字体大小。
答案 2 :(得分:17)
只需在par
中操纵您的参数即可。参数mar
控制单个图的边距大小。将您的par
更改为此:
par(mfrow = c(2,2), mar=c(1, 4, 1, 1) + 0.1)#it goes c(bottom, left, top, right)
答案 3 :(得分:2)
您需要一个条件评估,分配适合定位的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值的丢失中看出来,当你只将这个代码放入你的循环时。