Exported faceted plots are mutilated with ggsave() and alternatives, but render perfectly with RStudio export as JPEG

37 Views Asked by At

I have a large volume of plots to save and cannot practically export them manually, one at a time. However, when exporting with ggsave and other alternatives, the plot is butchered. Adjusting the plot size, scale, or any other parameter seems to have no effect.

    # Dummy data set
    question <- c("Q1. A very long text like this one is hard to use as a label.",
                  "Q2. A very long text like this one is hard to use as a label.",
                  "Q3. A very long text like this one is hard to use as a label.",
                  "Q4. A very long text like this one is hard to use as a label.",
                  "Q5. A very long text like this one is hard to use as a label.",
                  "Q6. A very long text like this one is hard to use as a label.",
                  "Q7. A very long text like this one is hard to use as a label.",
                  "Q8. A very long text like this one is hard to use as a label.",
                  "Q9. A very long text like this one is hard to use as a label.",
                  "Q10. A very long text like this one is hard to use as a label.",
                  "Q11. A very long text like this one is hard to use as a label.",
                  "Q12. A very long text like this one is hard to use as a label.",
                  "Q13. A very long text like this one is hard to use as a label.",
                  "Q14. A very long text like this one is hard to use as a label.",
                  "Q15. A very long text like this one is hard to use as a label.")
    
    variable <- c("V1","V2")
    set.seed(42)
    response <- round(runif(n = length(question) * length(variable), min = 1, max = 10), 0)
    
    # Create a data frame
    df_example <- expand.grid(Question = question, Variable = variable)
    df_example$Response <- rep(response, length.out = nrow(df_example))
    
    # Plot a bar chart
     p <- ggplot(df_example, aes(y = Variable, x = Response, fill = Variable)) +
        geom_bar(stat = "identity", position = "dodge") +
        facet_wrap(~Question, ncol = 1, strip.position = "left") +
        theme_minimal() +
        theme(
        legend.position = "none",
        axis.title.x = element_blank(),
        axis.title.y = element_blank(),
        strip.text.y.left = ggtext::element_textbox_simple(
          hjust = 0,
          padding = unit(c(0, 20, 0, 0), "pt")
        ),
        strip.placement = "outside"
      )
     
     ggsave("test_plot",  
            plot = p,
            device = "jpeg",
            scale = 1,
            width = 26.6,
            height = 15,
            units = "cm",
            dpi = 320)

Awesome plot exported as jpg by Rstudio: enter image description here

Mangled plot exported with ggsave: enter image description here

1

There are 1 best solutions below

2
SEAnalyst On

EDIT: Within ggtext::element_textbox_simple() you can specify the width of the text. Doing so will cause those question labels to wrap over two lines. Here is a complete example.

library(ggplot2)
library(ggtext)
#Example data
question <- c("Q1. A very long text like this one is hard to use as a label.",
              "Q2. A very long text like this one is hard to use as a label.",
              "Q3. A very long text like this one is hard to use as a label.",
              "Q4. A very long text like this one is hard to use as a label.",
              "Q5. A very long text like this one is hard to use as a label.",
              "Q6. A very long text like this one is hard to use as a label.",
              "Q7. A very long text like this one is hard to use as a label.",
              "Q8. A very long text like this one is hard to use as a label.",
              "Q9. A very long text like this one is hard to use as a label.",
              "Q10. A very long text like this one is hard to use as a label.",
              "Q11. A very long text like this one is hard to use as a label.",
              "Q12. A very long text like this one is hard to use as a label.",
              "Q13. A very long text like this one is hard to use as a label.",
              "Q14. A very long text like this one is hard to use as a label.",
              "Q15. A very long text like this one is hard to use as a label.")
variable <- c("V1","V2")
set.seed(42)
response <- round(runif(n = length(question) * length(variable), min = 1, max = 10), 0)

df_example <- expand.grid(Question = question, Variable = variable)
df_example$Response <- rep(response, length.out = nrow(df_example))

# Plot 
p <- ggplot(df_example, aes(y = Variable, x = Response, fill = Variable)) +
  geom_bar(stat = "identity", position = "dodge") +
  facet_wrap(~Question, ncol = 1, scales = "free_y", strip.position = "left") +
  theme_minimal() +
  theme(
    legend.position = "none",
    axis.title.x = element_blank(),
    axis.title.y = element_blank(),
    strip.text.y.left = element_textbox_simple(
      # Set width to control wrapping
      width = unit(5, "cm"), 
      hjust = 0,
      padding = margin(0, 20, 0, 0)
    ),
    strip.placement = "outside"
  )

#Save to file
ggsave("test_plot.jpeg",  
       plot = p,
       device = "jpeg",
       scale = 1,
       width = 26.6,
       height = 15,
       units = "cm",
       dpi = 320)

Original answer:

Try placing your 'Question' variable to y= aesthetic and 'Variable' to the fill= in your plot.

p <- ggplot(df_example, aes(x = Response, y = Question, fill = Variable)) +
  geom_bar(stat = "identity", position = "dodge") +
  theme_minimal() +
  labs(x = "Response", y = NULL) +
  theme_minimal() +
  theme(
    legend.position = "none",
    axis.title.x = element_blank(),
    axis.title.y = element_blank(),
    strip.text.y.left = ggtext::element_textbox_simple(
      hjust = 0,
      padding = unit(c(0, 0, 0, 0), "pt")
    ),
    strip.placement = "outside")

And then:

ggsave("test_plot.jpeg",  
       plot = p,
       device = "jpeg",
       scale = 1,
       width = 26.6,
       height = 15,
       units = "cm",
       dpi = 320)

test_plot