为 ggsave 中的最终图计算给定尺寸的面板尺寸(显示 geom_dotplot 的计数)

figuring out panel size given dimensions for the final plot in ggsave (to show count for geom_dotplot)

我正在尝试在 x 轴上显示点图的计数,如下所述: showing count on x-axis for dot plot

library(ggplot2)
library(grid)

date = seq(as.Date("2016/1/5"), as.Date("2016/1/12"), "day")
value = c(11,11,12,12,13,14,14,14)
dat =data.frame(date = date, value = value)

### base plot
g <- ggplot(dat, aes(x = value)) + geom_dotplot(binwidth = 0.8) + coord_flip()
g  # output to read parameter

### calculation of width and height of panel
current.vpTree()
seekViewport('panel.3-4-3-4')
real_width <- convertWidth(unit(1,'npc'), 'inch', TRUE)
real_height <- convertHeight(unit(1,'npc'), 'inch', TRUE)

### calculation of other values
height_coordinate_range <-diff(ggplot_build(g)$layout$panel_params[[1]]$y.range)
real_binwidth <- real_height / height_coordinate_range * 0.8  # 0.8 is the argument binwidth
num_balls <- real_width / 1.1 / real_binwidth  # the number of stacked balls. 1.1 is expanding value.

g + ylim(0, num_balls) 

但是,在我看来,real_width 指的是面板的宽度,而不是整个图。当我使用时,这会导致计数刻度和点之间的不对齐:

ggsave(g, 
       filename = "g.png", 
       path = getwd(),
       device = "png",
       height = real_height,
       width = real_width,
       units = "cm")

鉴于我想要一个 6cm x 6cm 的地块,我如何找出面板的尺寸,以便我可以使用面板尺寸来计算 num_balls

这个故事的寓意是:在绘制情节之前,您无法准确知道面板的大小。但是,您可以通过从输出维度中减去 plot decoration 的维度来近似它。这种方法忽略了在现实中,图形设备可以有一个影响文本真实大小的 'resolution'/'scaling' 参数。这里的原因是,由于面板是 'null' 个单位,因此在减去每个 non-null 个单位后,它们会适应输出维度的剩余部分。

library(ggplot2)
library(grid)

dat =data.frame(
  date = seq(as.Date("2016/1/5"), as.Date("2016/1/12"), "day"), 
  value = c(11,11,12,12,13,14,14,14)
)

g <- ggplot(dat, aes(x = value)) + geom_dotplot(binwidth = 0.8) + coord_flip()

output_width <- unit(6, "cm")
output_height <- unit(6, "cm")

# Convert plot to gtable
gt <- ggplotGrob(g)

# Find panel
is_panel <- grep("panel", gt$layout$name)
panel_location <- gt$layout[is_panel,]

# Note: panel width / heights are 'null' units
gt$widths[panel_location$l]
#> [1] 1null
gt$heights[panel_location$t]
#> [1] 1null

# Get widths/heights of everything except the panel
width  <- gt$widths[-panel_location$l]
height <- gt$heights[-panel_location$t]

# Calculate as output size - size of plot decoration
panel_height <- output_height - sum(height)
panel_width  <- output_width - sum(width)

convertUnit(panel_height, "cm")
#> [1] 4.6283951674277cm
convertUnit(panel_width, "cm")
#> [1] 4.57547850076103cm

reprex package (v2.0.1)

于 2022-02-24 创建

有一些方法可以固定面板的尺寸,这会使事情变得更容易,但这不是问题所在。