私は本当に素晴らしいライブラリggplot2を使用しています。 coord_fixed
を使用して、プロットのアスペクト比を設定する方法を理解しました。ここで、プロットをPDFに指定された幅(例:10 cm)で保存し、必要な高さを計算させたいのですが、これを実現する方法がわかりませんでした。これですか?可能ですか?
グリッド関数を使用して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)
sizeit(p2, 2)
バプティストの答えに基づいて、私は彼のコードを削除して、地理理論で示唆されているアスペクト比を返しました。これは私にとってはるかに便利でした。なぜなら、固定の幅または高さが必要であり、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]
}
よくわかりませんが、あなたが求めているのはこのようなものですか?
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を保存
ggsave
を使用すると、グラフィックデバイスの幅と高さを簡単に指定できます。プロット自体のアスペクト比を指定する場合は、グラフィックデバイスにこのアスペクト比を(大まかに)設定することもお勧めします。 height
を保存するときのwidth
とpdf
の単位はインチです。
_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)
_
多くの空白につながります。次のggsave
呼び出しは、アスペクト比にはるかに適合していますが、この量の空白はありません(大きな画像の場合は申し訳ありませんが、最大サイズを設定できませんでした:)):
_ggsave("plt.png", width = 2, height = 7)
_
より単純な解決策は、デフォルトのマージンでプロットを保存し、結果の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 を使用できます ここ 。