我有一个产生 60 个图的 for 循环。我想将所有这些图保存在一个文件中。如果我设置par(mfrow=c(10,6))
它说:Error in plot.new() : figure margins too large
我能做些什么?
我的代码如下:
pdf(file="figure.pdf")
par(mfrow=c(10,6))
for(i in 1:60){
x=rnorm(100)
y=rnorm(100)
plot(x,y)
}
dev.off()
我有一个产生 60 个图的 for 循环。我想将所有这些图保存在一个文件中。如果我设置par(mfrow=c(10,6))
它说:Error in plot.new() : figure margins too large
我能做些什么?
我的代码如下:
pdf(file="figure.pdf")
par(mfrow=c(10,6))
for(i in 1:60){
x=rnorm(100)
y=rnorm(100)
plot(x,y)
}
dev.off()
Output the plots to a pdf:
X = matrix(rnorm(60*100), ncol=60)
Y = matrix(rnorm(60*100), ncol=60)
pdf(file="fileName.pdf")
for(j in 1:60){
plot(X[,j], Y[,j])
}
dev.off()
Your default plot, as stated in the loop, does not use the space very effectively. If you look at just a single plot, you can see it has large margins, both between axis and edge and plot area and axis text. Effectively, there is a lot of space-hogging.
Secondly, the default pdf-function creates small pages, 7 by 7 inches. That is not a large sheet to plot on.
Trying to plot a 10 x 6 or 12 x 5 on 7 by 7 inches is therefore trying to squeeze in a lot of whitespace on very little space.
For it to succeed, you must look into the margin-options of par
which is mar
, mai
, oma
and omi
, and probably some more. Consult the documentation with the command
?par
In addition to this, you could consider not displaying axis-text, tick-marks, tick-labels and titles for every one of the 60 sub-plots, as this too will save you space.
But somebody has already gone through some of this trouble for you. Look into the lattice
-package or ggplot2
, which has some excellent methods for making table-like subplots.
But there is another pressing issue: What are you trying to display with 60 subplots?
Update
Seeing what you are trying to do, here is a small example of faceting in ggplot2
. It uses the Tufte-theme from jrnold's ggthemes, which is copied into here and then modified slightly in the line after the function.
library(ggplot2)
library(scales)
#### Setup the `theme` for the plot, i.e. the appearance of background, lines, margins, etc. of the plot.
## This function returns a theme-object, which ggplot2 uses to control the appearance.
theme_tufte <- function(ticks=TRUE, base_family="serif", base_size=11) {
ret <- theme_bw(base_family=base_family, base_size=base_size) +
theme(
legend.background = element_blank(),
legend.key = element_blank(),
panel.background = element_blank(),
panel.border = element_blank(),
strip.background = element_blank(),
plot.background = element_blank(),
axis.line = element_blank(),
panel.grid = element_blank())
if (!ticks) {
ret <- ret + theme(axis.ticks = element_blank())
}
ret
}
## Here I modify the theme returned from the function,
theme <- theme_tufte() + theme(panel.margin=unit(c(0,0,0,0), 'lines'), panel.border=element_rect(colour='grey', fill=NA))
## and instruct ggplot2 to use this theme as default.
theme_set(theme)
#### Some data generation.
size = 60*30
data <- data.frame(x=runif(size), y=rexp(size)+rnorm(size), mdl=sample(60,size, replace=TRUE))
#### Main plotting routine.
ggplot(data, aes(x,y, group=mdl)) ## base state of the plot to be used on all "layers", i.e. which data to use and which mappings to use (x should use x-variable, y should use the y-variable
+ geom_point() ## a layer that renders data as points, creates the scatterplot
+ stat_quantile(formula=y~x) ## another layer that adds some statistics, in this case the 25%, 50% and 75% quantile lines.
+ facet_wrap(~ mdl, ncol=6) ## Without this, all the groups would be displayed in one large plot; this breaks it up according to the `mdl`-variable.
The usual challenge in using ggplot2
is restructuring all your data into data.frames. For this task, the reshape2
and plyr
-packages might be of good use.
For you, I would imagine that your function that creates the subplot both calculates the estimation and creates the plot. This means that you have to split the function into calculating the estimation, returning it to a data.frame
, which you then can collate and pass to ggplot
.
为了在页面或文档上放置许多图(我已经创建了包含数千个图的图像),可以方便地将工作分开- 它单独R
创建图- 和其他更适合安排的软件事物的数组。如果这让您想起了电子表格或文字处理表,那么我们的想法是一样的。
此页面是 PDF 文件的屏幕截图,包含 200 多个统计图形。尽管为了掩盖专有数据,它已大大缩小(至标称尺寸的 40%),但原件具有原始R
图形的所有细节,并且可以毫无问题地缩放到 1600%。
两种机制运作良好。对于多达数百个绘图,将一组位图图像文件(.emf 或 .wmf)导入并重新排序到 Word 文档中的小宏就可以了。为了更好地控制,我求助于一个类似的 Excel 宏。它由一个除了包含列标题的行和包含行标题的列之外没有其他内容的工作表驱动。(您可以在图的左侧和顶部看到它们。)宏删除该工作表上的所有其他内容(格式除外),然后将行和列标题的每个可能组合转换为文件名,如果找到该文件,它将其导入相应的单元格。数千张图像的整个操作仅需几秒钟。
显然,与其他软件之间的这种通信机制R
是原始的,由一组具有标准命名约定的图像文件组成。但是实现这一切所需的代码很简短(尽管针对每种情况进行了定制)并且工作可靠。例如,如果您将绘图代码封装在一个函数中,那么它将在一个循环中调用以创建许多相似的绘图。在该函数的末尾添加几行以将绘图保存到文件中,如下所示:
path <- "W: <whatever>/" # Folder for the output files
ext <- "wmf" # or "emf" or "png" or ... # Format (and extension) of the output
...
if (save) {
outfile <- paste(path, paste(munge(well), munge(parm), sep="_"), sep="/")
outfile <- paste(outfile, ext, sep=".")
savePlot(filename=outfile, type=ext)
}
在这种情况下,每个图由两个循环变量well
和标识,这两个变量parm
都是字符串(它们对应于列和行标题)。创建可接受的文件名的功能只是去掉标点符号,用一个无痛的占位符代替它:
munge <- function(s) gsub("[[:punct:]]", "_", s)
一旦将这些图像导入 Word、Excel 或您喜欢的任何位置,就可以很容易地重新组织它们,在它们周围放置其他材料等,然后以 PDF 格式打印结果。
创造这些非常大的“小倍数”(用塔夫特的术语)是一门艺术。在可能的范围内,它有助于遵循 Tufte 的原则,即通过擦除不必要的材料来增加数据:墨水的比例。这使得图形模式清晰,即使画面已大大缩小以便一次理解其所有行和列。尽管上图是一个糟糕的例子——各个图必须有轴、网格线、标签等,以便在缩放时可以详细阅读——这种方法的强大功能可以揭示模式即使在这个规模上也很清楚。使情节相互可比是至关重要的。在这个由时间序列组成的示例中,每个图在 x 轴上具有相同的范围;在每一行内(对应于不同类型的观察),y 轴上的范围是相同的;并且所有的配色方案和符号化方法自始至终都是相同的。
你也可以使用knitr
. 这并没有立即转换为基本图形(我现在必须运行),但使用起来ggplot
很容易。
\documentclass{article}
\begin{document}
<<echo = FALSE, fig.keep='high', fig.height=3, fig.width=4>>=
require(ggplot2)
for (i in 1:10) print(ggplot(mtcars, aes(x = disp, y = mpg)) + geom_point())
@
\end{document}
上面的代码将生成一个包含所有图表的漂亮的多页 pdf。
对于此类问题的一个非常简单的解决方案,我发现设置一个大的“Windows”设备可以使窗口足够大以供多种用途。
windows(50,50)
par(mfrow=c(10,6))
for(i in 1:60){
x=rnorm(100)
y=rnorm(100)
plot(x,y)
}
或者在我的情况下,
windows(20,20)
plot(Plotting_I_Need_In_Rows_of_4, mfrow=c(4,4))