为啥 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*resppi(请参阅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 文件太大而截屏):

然后可以在预览中调整大小。

字体大小

由于pointsizeres 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 图像中的点大小。所以:

18pts/577*1050/300*72=7.86pts 16pts/577*1050/300*72=6.99pts 14pts/577*1050/300*72=6.11pts

这些是我应该在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.4 lines 是一个单位,其中 "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 模拟器开不起来了

为啥 Android Studio 将我所有的引用从 R 更改为 android.R?

为啥 Android Studio 将我所有的引用从 R 更改为 android.R?

打开Tiff文件为啥显示为黑白色

为啥 FindMimeFromData 可以识别一台主机上的图像/tiff,但不能识别另一台主机上的图像/tiff?

为啥我在 Tesseract 中收到“tiff page 1 not found”Lebtonica 警告?