web-dev-qa-db-ja.com

指定されたアスペクト比でプロットを保存します

私は本当に素晴らしいライブラリggplot2を使用しています。 coord_fixedを使用して、プロットのアスペクト比を設定する方法を理解しました。ここで、プロットをPDFに指定された幅(例:10 cm)で保存し、必要な高さを計算させたいのですが、これを実現する方法がわかりませんでした。これですか?可能ですか?

22
marsl

グリッド関数を使用してggplotgrobのフルサイズを計算できますが、(edit:少なくとも)2つの注意点があります。

  • 単位変換を行うために、追加のデバイスウィンドウが開きます

  • プロットパネルのサイズは、デフォルトでは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)

enter image description here

sizeit(p2, 2)

enter image description here

14
baptiste

バプティストの答えに基づいて、私は彼のコードを削除して、地理理論で示唆されているアスペクト比を返しました。これは私にとってはるかに便利でした。なぜなら、固定の幅または高さが必要であり、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]
}
4
morty

よくわかりませんが、あなたが求めているのはこのようなものですか?

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 x6.93を保存

2
Dennis

ggsaveを使用すると、グラフィックデバイスの幅と高さを簡単に指定できます。プロット自体のアスペクト比を指定する場合は、グラフィックデバイスにこのアスペクト比を(大まかに)設定することもお勧めします。 heightを保存するときのwidthpdfの単位はインチです。

_ggplot(...) # make a plot here
ggsave("plot.pdf", width = 10)
_

これで、10cmをインチに変換するだけで済みます。さらに、heightは、指定しない場合、特定のアスペクト比に強制されません。 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)
_

enter image description here 多くの空白につながります。次のggsave呼び出しは、アスペクト比にはるかに適合していますが、この量の空白はありません(大きな画像の場合は申し訳ありませんが、最大サイズを設定できませんでした:)):

_ggsave("plt.png", width = 2, height = 7)
_

enter image description here

0
Paul Hiemstra

より単純な解決策は、デフォルトのマージンでプロットを保存し、結果のpngを ImageMagick でトリミングすることです。

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")

確かに、トリミングは使用する出力デバイスによって異なります。例えば。 pdfの場合、説明されているように pdfcrop を使用できます ここ

0
Holger Brandl