Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 以给定的纵横比保存绘图_R_Ggplot2_Gtable - Fatal编程技术网

R 以给定的纵横比保存绘图

R 以给定的纵横比保存绘图,r,ggplot2,gtable,R,Ggplot2,Gtable,我正在与非常棒的图书馆ggplot2合作。我通过使用coord\u fixed了解了如何设置绘图的纵横比。现在,我想将绘图保存为指定宽度(例如10厘米)的PDF格式,并计算出所需的高度。我不知道如何做到这一点。这可能吗?如果使用ggsave您只需指定图形设备的宽度和高度即可。如果指定绘图本身的纵横比,在图形设备中使用此纵横比(大致)也很好。保存pdf时高度和宽度的单位为英寸: ggplot(...) # make a plot here ggsave("plot.pdf", width = 10

我正在与非常棒的图书馆ggplot2合作。我通过使用
coord\u fixed
了解了如何设置绘图的纵横比。现在,我想将绘图保存为指定宽度(例如10厘米)的PDF格式,并计算出所需的高度。我不知道如何做到这一点。这可能吗?

如果使用
ggsave
您只需指定图形设备的宽度和高度即可。如果指定绘图本身的纵横比,在图形设备中使用此纵横比(大致)也很好。保存
pdf
高度和
宽度的单位为英寸:

ggplot(...) # make a plot here
ggsave("plot.pdf", width = 10)
现在只需将10厘米转换为英寸。此外,如果未指定某个纵横比,
高度
,则不会强制将其设置为该纵横比。如果需要16:9的纵横比,可以根据宽度轻松计算高度:

ggplot(...) # make plot
width = 10
height = (9/16) * width
ggsave("plot.pdf", width = width, height = height)
如果您真的愿意,可以将其封装在函数中


编辑:关键是要同步绘图的纵横比(通过
coord_fixed()
)和图形设备的纵横比。比如说

library(ggplot2)
ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point() + coord_fixed()
ggsave("plt.png", width = 7, height = 7)
导致大量空白。而下面的
ggsave
调用在纵横比上有更好的匹配性,但没有这么大的空白(很抱歉,图片太大了,无法设置最大大小:):


不确定,但像这样的东西是你想要的吗

ggplot(data.frame(x = seq(10), y = seq(10)), aes(x = x, y = y)) +
    geom_point() +
    coord_equal() +
    theme(aspect.ratio = 1)
我觉得这很好:

ggsave("test.pdf", width = 4, height = 4)
空白太多,但图形本身的纵横比为1:

ggsave("test2.pdf", width = 4)
信息:
在图像中保存4 x 6.93

您可以使用网格函数来计算ggplot grob的完整大小,但有(编辑:至少)两个注意事项:

  • 将打开一个额外的设备窗口,以进行单位转换

  • 打印面板大小默认为0,因为它是根据它所在的设备(视口)动态计算的,而不是相反

也就是说,下面的函数试图打开一个完全符合ggplot的设备

library(ggplot2)
library(grid)

sizeit <- function(p, panel.size = 2, default.ar=1){

  gb <- ggplot_build(p)
  # first check if theme sets an aspect ratio
  ar <- gb$plot$coordinates$ratio

  # second possibility: aspect ratio is set by the coordinates, which results in 
  # the use of 'null' units for the gtable layout. let's find out
  g <- ggplot_gtable(gb)
  nullw <- sapply(g$widths, attr, "unit")
  nullh <- sapply(g$heights, attr, "unit")

  # ugly hack to extract the aspect ratio from these weird units
  if(any(nullw == "null"))
    ar <- unlist(g$widths[nullw == "null"]) / unlist(g$heights[nullh == "null"])

  if(is.null(ar)) # if the aspect ratio wasn't specified by the plot
       ar <- default.ar

  # ensure that panel.size is always the larger dimension
  if(ar <= 1 ) panel.size <- panel.size / ar

  g$fullwidth <- convertWidth(sum(g$widths), "in", valueOnly=TRUE) + 
    panel.size
  g$fullheight <- convertHeight(sum(g$heights), "in", valueOnly=TRUE) + 
    panel.size / ar

  class(g) <- c("sizedgrob", class(g))
  g
}


print.sizedgrob <- function(x){
  # note: dev.new doesn't seem to respect those parameters
  # when called from Rstudio; in this case it 
  # may be replaced by x11 or quartz or ...
  dev.new(width=x$fullwidth, height=x$fullheight)
  grid.draw(x)
}


p1 <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point() + coord_fixed() +
  theme(plot.background = element_rect(colour = "red"))

p2 <- p1 + aes(x = mpg, y = wt)

# need for an explicit dummy device open, otherwise it's a bit off
# for no apparent reason that I can understand
dev.new() 

sizeit(p1, 0.1)

根据巴普蒂斯特的回答,我将他的代码精简为返回geotheory建议的纵横比。这对我来说方便多了,因为我要么想要一个固定的宽度或高度,要么通过一个现有的包装器函数传递所有内容,该函数还将字体添加到我的pdf中

哦,如果你使用了刻面,你需要手动考虑它们。按行除,按列乘。不确定是否有更好的方法

ggGetAr <- function(p, default.ar=-1){

    gb <- ggplot_build(p)
    # first check if theme sets an aspect ratio
    ar <- gb$plot$coordinates$ratio

    # second possibility: aspect ratio is set by the coordinates, which results in 
    # the use of 'null' units for the gtable layout. let's find out
    g <- ggplot_gtable(gb)
    nullw <- sapply(g$widths, attr, "unit")
    nullh <- sapply(g$heights, attr, "unit")

    # ugly hack to extract the aspect ratio from these weird units
    if(any(nullw == "null"))
        ar <- unlist(g$widths[nullw == "null"]) / unlist(g$heights[nullh == "null"])

    if(is.null(ar)) # if the aspect ratio wasn't specified by the plot
        ar <- default.ar

    ar[1]
}

ggGetAr一个更简单的解决方案是使用默认边距保存绘图,并使用默认边距修剪生成的png


当然,根据所使用的输出设备,修剪会有所不同。例如,如果是pdf,您可以按说明使用。

我认为是Paul,但那是设备的大小,而不是绘图。添加标题、轴标签和图例等后,打印区域本身可能不是方形的,并且使用
coord_fixed()
打印区域本身不会填充可用空间。我不知道除了调整打印窗口的大小之外还有什么好办法,直到
ggsave()
不指定宽度就能得到10厘米宽的图像。谢谢你的回答。加文,这正是你在评论中指出的。我认为这是一个相当大的问题,必须手动裁剪每个地块。让我们拭目以待,看看是否有人提出了解决方案。谢谢你的回答,丹尼斯。不幸的是,这不合适,因为默认情况下,
ggsave
仅采用当前绘图窗口的大小。谢谢您的回答,baptiste。似乎没有什么好办法。我接受了你的答案,因为我认为没有更好的办法出现。谢谢大家,这对我没用。当我把你的
sizeit(p1,0.1)
plot保存(到pdf)时,输出奇怪地变换了轴。我认为最好使用一个函数,返回用于确定ggsave WITH和HEIGH参数的纵横比。
sizeit(p2, 2)
ggGetAr <- function(p, default.ar=-1){

    gb <- ggplot_build(p)
    # first check if theme sets an aspect ratio
    ar <- gb$plot$coordinates$ratio

    # second possibility: aspect ratio is set by the coordinates, which results in 
    # the use of 'null' units for the gtable layout. let's find out
    g <- ggplot_gtable(gb)
    nullw <- sapply(g$widths, attr, "unit")
    nullh <- sapply(g$heights, attr, "unit")

    # ugly hack to extract the aspect ratio from these weird units
    if(any(nullw == "null"))
        ar <- unlist(g$widths[nullw == "null"]) / unlist(g$heights[nullh == "null"])

    if(is.null(ar)) # if the aspect ratio wasn't specified by the plot
        ar <- default.ar

    ar[1]
}
require(ggplot2)
require(dplyr)

ggplot(iris, aes(Sepal.Length, Sepal.Width)) + geom_point() + coord_fixed(0.3)
ggsave("untrimmed.png")


system("convert untrimmed.png -trim -bordercolor white -border 20  reframed.png")