Home > Blockchain >  figuring out panel size given dimensions for the final plot in ggsave (to show count for geom_dotplo
figuring out panel size given dimensions for the final plot in ggsave (to show count for geom_dotplo

Time:03-01

I'm trying to show the count for dotplot on the x-axis as outlined here: 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) 

However, it seems to me that real_width refers to width of the panel, not the whole plot. This leads to a misalignment between count ticks and dots when I use:

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

Given I want a plot that is 6cm x 6cm, how can i find out the dimensions of the panel, so that I can use the panel dimensions to calculate num_balls?

CodePudding user response:

The moral of the story is: you can't know the panel size exactly until the plot is being drawn. However, you can approximate it by subtracting the dimensions of plot decoration from the output dimension. This approach ignores that in reality, graphics devices can have a 'resolution'/'scaling' parameter that effects the true size of the text. The reasoning here is that since panels are 'null' units, they adapt to whatever is left of the output dimension, after every non-null units have been subtracted.

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

Created on 2022-02-24 by the reprex package (v2.0.1)

There are ways to fix the dimensions of a panel that would make things easier, but that wasn't the question.

  • Related