为啥 tiff 输出看起来与 R studio 中的 ggplot2 输出不同?
Posted
技术标签:
【中文标题】为啥 tiff 输出看起来与 R studio 中的 ggplot2 输出不同?【英文标题】:Why does the tiff output look different than the ggplot2 output in R studio?为什么 tiff 输出看起来与 R studio 中的 ggplot2 输出不同? 【发布时间】:2015-03-25 02:39:19 【问题描述】:我正在使用最新版本的 R studio 中的 ggplot2 制作出版质量图。
它们需要以 300 dpi 的分辨率保存为 TIFF。
当我运行代码并在命令控制台中调用绘图时,它完美地显示在绘图窗口中。但是,当我将其保存为具有宽度、高度和分辨率命令的 tiff 时,当我在图像查看器中打开 tiff 时,它看起来完全是一团糟。字体很大,图例很大而且错位等等。
我尝试从 R Studio 绘图窗口导出图像,但我只有高度和宽度选项。因为我想要一个 300 dpi 的图形,它将是 3.5 x 2.33 我知道宽度:高度将为 1050:699(像素)。但是,也许我误解了这个条目。
也许,我应该以英寸为单位输入高度和宽度。如果我这样做,那么我该如何指定 dpi?
我已经使用 tiff 命令保存了我的情节。这是从 Cookbooks forR 借来的可重现示例
set.seed(955)
dat <- data.frame(cond = rep(c("A", "B"), each=10),
xvar = 1:20 + rnorm(20,sd=3),
yvar = 1:20 + rnorm(20,sd=3))
library(ggplot2)
test <- ggplot(dat, aes(x=xvar, y=yvar, color=cond)) +
geom_point(shape=1) +
scale_colour_hue(l=50) + # Use a slightly darker palette than normal
geom_smooth(method=lm, # Add linear regression lines
se=FALSE) +
theme(legend.position=c(.75,.38),
axis.title.y = element_text(colour="black", size = 18),
axis.title.x = element_text( colour="black", size = 18),
axis.text.x=element_text(colour="black", size= 16),
axis.text.y=element_text( colour="black", size = 16),
plot.title=element_text(size=14), # changing size of plot title)+
legend.text=element_text( size=16))
tiff("test.tiff", width= 1050, height= 699, units="px", res=300)
plot(test)
dev.off()
当我使用“预览”打开它时,它看起来非常糟糕。我希望它看起来与绘图窗口中的完全一样,但以特定的 dpi 保存。我究竟做错了什么?我有什么误解?
谢谢!
【问题讨论】:
你试过简单地使用ggsave
吗?
绘图窗口不是完成绘图的地方。当您准备具有特定尺寸的生产图形时,您应该计划需要在该设备中调整大小和调整内容。使用默认绘图窗口是原型设计。
@Gregor.. 好吧,看来缩放字体大小、图例位置等只是一个反复无常的过程?
您最好的选择是使用与所需绘图尺寸相同的交互式图形设备。在windoze上,咒语是windows(1050, 699)
,我认为在Mac上相当于X11()
。您还可以使用缩放功能创建一个弹出的绘图窗口,然后缩放到相同的所需尺寸。
以下代码将始终生成 1050x699 像素的图像,但更改 n
将更改边距和文本缩放。试验 1.2 到 4 之间的值。n = 1.5; tiff("test.tiff", width=3.5*n, height=2.33*n, units="in", res=300/n); print(test); dev.off()
【参考方案1】:
这是一个很大的痛苦,因为你必须调整很多属性......但它可以做到。问题是字体、点和线大小的默认设置与 1/72 英寸的比例相关,R/RStudio 图像的默认分辨率为 72ppi。当您使用更高的分辨率时,这些尺寸会按像素比例变大,因此您必须同时调整 RStudio 窗口的大小和分辨率。
我建议的简单解决方案是使您的绘图开始时远大于 1050x699px,然后在 Rstudio 之外调整其大小以进行发布。但是,如果您真的想完全在 R 中完成它,您可以。
需要注意的关键是:
R 和 RStudio 图像的默认分辨率为 72ppi 当前 RStudio 图像窗口的大小可以通过dev.size()
确定
pointsize
aka bigpts
是相对于英寸的,被解释为 1/72 英寸。因此,它以像素数显示为pointsize
/72inches*res
ppi(请参阅unit)
ggplot2
图层具有点、线等属性的默认设置,可以通过str(test)
查看。
ggplot2
的默认主题属性,如图例字体大小、图例标题大小、图例框间距可以用theme_get()
查看
legend.position
是 determined by values from 0 to 1, where bottom-left is 0,0 and top-right is 1,1
对于放错位置的图例意味着,图例的坐标可能很好,因为它是一个相对位置,但需要重新计算图例的其他属性,例如边距或标题大小。对于未调整大小的字体,这意味着必须根据res
ppi 和 Rstudio 窗口的大小重新计算大小。由于未在theme
中指定未指定大小的行,这意味着它们必须相对于theme_get()
中的默认值重新计算。我将分段分解每个组件的解决方案。
RStudio 窗口
我将首先在我的默认 Rstudio 窗口中发布绘图如何显示的屏幕截图(使用 MacBook 上的屏幕截图实用程序拍摄):
我可以使用dev.size("px")
获取我的 Rstudio 窗口的大小(以像素为单位)。我的恰好是:
> dev.size("px")
[1] 577 563
我的 RStudio 窗口比所需 TIFF 图的尺寸更方形。这意味着纵横比将不准确,更多取决于用户。就我而言,我将尝试纠正与窗口宽度相关的问题,577
。
你目前可能拥有的
当您执行问题中的代码时,您最终可能会得到如下图像:
> test <- ggplot(dat, aes(x=xvar, y=yvar, color=cond)) +
geom_point(shape=1) +
scale_colour_hue(l=50) + # Use a slightly darker palette than normal
geom_smooth(method=lm, # Add linear regression lines
se=FALSE) +
theme(legend.position=c(.75,.38),
axis.title.y = element_text(colour="black", size = 18),
axis.title.x = element_text( colour="black", size = 18),
axis.text.x=element_text(colour="black", size= 16),
axis.text.y=element_text( colour="black", size = 16),
plot.title=element_text(size=14), # changing size of plot title)+
legend.text=element_text( size=16))
>
> tiff("test.tiff", width= 1050, height= 699, units="px", res=300)
>
> plot(test)
> dev.off()
很丑;一切都需要调整。
简单的解决方案
诚实地使 TIFF 文件更大,然后在预览中手动调整大小是最简单的方法。为了保持与 RStudio 窗口中的外观相同,您需要按 ppi 比率进行调整。因此,对于我们的绘图,我们将有 577px*300ppi/72ppi=2404px。等效高度将是 2404px*699px/1050px = 1600px。
tiff("test2.tiff", width= 2404, height= 1600, units="px", res=300)
plot(test)
dev.off()
结果(由于 TIFF 文件太大而截屏):
然后可以在预览中调整大小。
字体大小
由于pointsize
在res
ppi 处为 1/72 英寸,因此在 Rstudio 图中,这意味着轴标题为 18 x 1/72 英寸 x 72ppi = 18 像素。所以 1 点 = 1 像素。在宽度 = 577 像素的绘图上,轴标题所占绘图的比例因此为 18/577=0.032。因此,在 72ppi 宽度 = 1050 像素的绘图上,我想要 18/577*1050=32.76 点字体。但是,我的情节实际上是在 300ppi 时 width=1050pixels。所以我还需要通过绘图之间的 ppi 之间的比率进行调整,72ppi/300ppi。这给了我 32.76point/300*72=7.86 点来获得与我的 Rstudio 窗口中相同的字体。因此,我的公式是 x/577*1050/300*72 从我的 Rstudio 窗口中的点大小转换为我的 TIFF 图像中的点大小。所以:
这些是我应该在theme
参数中实际输入的点。
线条和点的大小
没有指定线和点的大小,所以我们必须从test$layers
获取它:
#layers[[1]] is geom_point
> point_size<-test$layers[[1]]$geom$default_aes$size
> point_size
[1] 1.5
#layers[[2]] is geom_smooth
> line_size<-test$layers[[2]]$geom$default_aes$size
> line_size
[1] 1
使用与上面相同的逻辑,这意味着我们想要尺寸:
1.5/577*1050/300*72=0.66 1/577*1050/300*72=0.44图例位置
在示例中,图例位置为c(.75,.38)
。这很好,但由于 1)我的 Rstudio 窗口大部分是方形的,以及 2)图例的其他属性,例如边距大小和框大小,因此主观上可能看起来放错了位置。我可以通过theme_get()
获得这些其他属性:
> theme_get()$legend.margin
[1] 5.5pt 5.5pt 5.5pt 5.5pt
> theme_get()$legend.key.size
[1] 1.2lines
这给了我们:
5.5/577*1050/300*72=2.4lines
是一个单位,其中 "Locations and dimensions are in terms of multiples of the default text size of the viewport (as specified by the viewport's fontsize and lineheight)." 由于它仍然由 fontsize 和 lineheight 指定,我们可以进行相同的计算:1.2/577*1050/300*72=0.52。
把它们放在一起
将上面的代码sn-p放在一起,我们会输入:
test<- ggplot(dat, aes(x=xvar, y=yvar, color=cond)) +
geom_point(shape=1,size=0.66) +
scale_colour_hue(l=50) + # Use a slightly darker palette than normal
geom_smooth(method=lm, # Add linear regression lines
se=FALSE,size=0.44)+
theme(legend.position=c(.75,.38),
axis.title.y = element_text(colour="black", size = 7.62),
axis.title.x = element_text( colour="black", size = 7.62),
axis.text.x=element_text(colour="black", size= 6.99),
axis.text.y=element_text( colour="black", size = 6.99),
plot.title=element_text(size=6.11), # changing size of plot title)+
legend.text=element_text( size=6.11),
legend.title=element_text(size=6.11), # legend title size wasn't specified originally
legend.margin=margin(t=2.4,r=2.4,b=2.4,l=2.4),
legend.key.size = unit(0.52,"lines"))
tiff("test.tiff", width= 1050, height= 699, units="px", res=300)
plot(test)
dev.off()
这给了我们
这似乎足够接近。 (图例位置不太一样,但我们也从方形变成了矩形)
一些补充说明
一种大大简化计算并且能够更好地比较图例位置的方法是从 1050x699 像素的窗口大小开始,而不是我的方形窗口。然后您只需将线条和字体大小调整为 72/300,而不是额外的窗口大小调整。我做了一个随机的不同大小来显示窗口大小和分辨率的结合。
当然,除了精确计算之外,另一种方法是玩弄点、字体、线、边距等大小,直到得到你喜欢的东西。
【讨论】:
非常有用的解决方案。感谢您的解释。【参考方案2】:上面 Joran 的评论似乎是正确的答案。从上面的示例中,尝试...
ggsave(filename = "test2.tiff", plot = test)
默认情况下,ggsave()
输出为 300 dpi,并会通过您的扩展猜测输出类型。它将使您的绘图看起来就像在绘图窗口中一样,因为它使用grDevices::dev.size()
获取绘图窗口大小。我猜在示例中传递给tiff()
的像素尺寸与绘图窗口的尺寸不同。这就是保存的绘图看起来不同的原因。
如果您使用dev.size()
获取当前绘图设备的尺寸,您应该能够使用tiff()
保存绘图,但是在处理类对象时使用ggsave()
包装器通常更容易ggplot
.
【讨论】:
【参考方案3】:您的问题是 3.5 x 2.33 英寸是一个相当小的数字。文本大小为 18 或 16 意味着图的其余部分没有太多空间。例如,18pt 字体是 0.25 英寸或 2.33 英寸高的绘图高度的 10%。如果 RStudio 中的绘图窗口大于最终图形大小,则绘图将需要看起来不同。一般来说,为所有情节元素获得正确的尺寸需要一些试验和错误。我建议通过以英寸为单位指定 tiff 大小来避免任何混淆。
tiff("test.tiff", width= 3.5, height= 2.33, units="in", res=300)
plot(test)
dev.off()
为了避免每次你可以按照 Andrie 在评论中所说的那样打开新的 tiff 并创建一个适当大小的交互式窗口:
windows(3.5, 2.33)
请注意,默认单位是英寸。
通过这种方式,您可以交互式地调整绘图以适应可用空间。还需要注意的是,打开 tiff 文件时打开的窗口大小与创建文件时指定的大小不同,因此可能会拉伸图像以适应窗口。
【讨论】:
以上是关于为啥 tiff 输出看起来与 R studio 中的 ggplot2 输出不同?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Android Studio 将我所有的引用从 R 更改为 android.R?
为啥 Android Studio 将我所有的引用从 R 更改为 android.R?