0

I'm trying to remove the extra spacing shown in red on this graph:

1

I have a lot of theme code, so it could be from something there, but I've looked through it several times and haven't been able to figure it out. I also recently found out that the labels look normal before I save the graph so I was wondering if the spacing is added when saving it. I can't change the resolution in the output window, though, so I think I need to save it as an image.

So far I've tried adjusting panel spacing, changing text size, and changing some of the theme values. I've been researching this for a few hours, but I'm using label_date_short which I can't find much about.

I'm just using test data right now, this is what it looks like:

structure(list(values = c(20, 40, 30, 50, 90, 20), test_timestamps = structure(c(1636990200, 
1637678400, 1638608400, 1637042400, 1638698400, 1638608400), class = c("POSIXct", 
"POSIXt"), tzone = "EST")), row.names = c(NA, 6L), class = "data.frame")

This is my main code:

library(ggplot2)
library(scales)
library(ragg)

# the larger sizes for the graph are because the text shrinks when I change the resolution
test_plot <- ggplot(test_data, aes(x=test_timestamps)) + 
  geom_smooth(aes(y=values), 
              method="loess", 
              formula=y~x) + # a smooth line graph with shadow error
  scale_color_manual(name="Variables", "blue") + # sets the data line colors based
  # x axis
  scale_x_datetime(name="Timestamps (2021)", # axis label
                   date_breaks = "4 days", # where the tick marks are
                   # no year, months are shorter, time is taken into account
                   labels=label_date_short(format = c(NA, "%b", "%d", "%H:%M")), 
                   expand=c(0,0)) + # takes away space on the inside edges of the plot 
  scale_y_continuous(name="Number of occurrences", 
                   expand = c(0, 0)) +
  ggtitle("Testing") + # title of graph
  theme_classic() + # simple theme (no grid lines, etc)
  theme(panel.spacing=unit(0, "lines"),
        text=element_text(family="quicksand", color="grey20"),
        plot.title=element_text(size=120, margin=margin(10, 0, 10, 0), hjust=0.5),
        plot.margin=unit(c(0.5, 0.5, 0.5, 0.5), "cm"),
        axis.title.y=element_text(margin=margin(0, 10, 0, 10), size=80), 
        axis.text.y=element_blank(),
        axis.ticks.y=element_blank(),
        axis.title.x=element_text(margin=margin(10, 0, 10, 0), size=80),
        axis.text.x=element_text(hjust=0.5, size=80),
        axis.ticks.length=unit(.2, "cm"),
        legend.key.size=unit(0.7, 'cm'),
        legend.title=element_text(size=60),
        legend.spacing.y=unit(0.5, 'cm'), 
        legend.spacing.x=unit(0.3, 'cm'), 
        legend.text=element_text(size=60),
        legend.background=element_rect(fill="gray95", size=.5))

This saves the graph as an image:

agg_png("test_plot2.png", res=500, height=6.5, width=7.5, units = "in")
print(test_plot)
dev.off()

I've also tried this to save the graph:

ggsave("test_plot.png", plot=test_plot, dpi=500, height=6.5, width=7.5, device=grDevices::png)
vimuth
  • 5,064
  • 33
  • 79
  • 116
  • I think some of the methods here should apply: https://stackoverflow.com/a/44616739/6851825 – Jon Spring Aug 02 '22 at 18:11
  • 1
    I think the large text in your theme is causing the issue. It makes a nice looking graph without your theme calls, I think with the huge text size when you render as image it is trying to fit everything in a nice way. I would get rid of all the them elements and adding changes one at at a time. – BEVAN Aug 02 '22 at 18:17
  • 1
    Have you noticed you have axis text elements of size **80**? And `plot.title` text of size **120**? – Rui Barradas Aug 02 '22 at 18:19
  • 80pt font is 1.1 inches tall. So specifying `height = 6.5` inches and `size = 80` pt for your axis title and axis text is asking for fully 1/3 of the height of the plot to be taken up by axis title and axis text. (1.1 * 2 / 6.5 ~ 0.34) – Gregor Thomas Aug 02 '22 at 18:23

1 Answers1

1

You might use this approach to put the month into some of the axis labels themselves:

library(lubridate); library(dplyr)
ggplot(test_data, aes(test_timestamps, values)) +
  geom_smooth() +
  scale_x_datetime(
    date_breaks = "4 days",
    labels = function(x) if_else(
      is.na(lag(month(x))) | month(x) != lag(month(x)),
      paste(day(x), "\n", month(x, label = TRUE)),
      as.character(day(x)))
    )

enter image description here

Jon Spring
  • 55,165
  • 4
  • 35
  • 53