161

I need to output ggplot2 graphics from R to PNG files with transparent background. Everything is ok with basic R graphics, but no transparency with ggplot2:

d <- rnorm(100) #generating random data

#this returns transparent png
png('tr_tst1.png',width=300,height=300,units="px",bg = "transparent")
boxplot(d)
dev.off()

df <- data.frame(y=d,x=1)
p <- ggplot(df) + stat_boxplot(aes(x = x,y=y)) 
p <- p + opts(
    panel.background = theme_rect(fill = "transparent",colour = NA), # or theme_blank()
    panel.grid.minor = theme_blank(), 
    panel.grid.major = theme_blank()
)
#returns white background
png('tr_tst2.png',width=300,height=300,units="px",bg = "transparent")
p
dev.off()

Is there any way to get transparent background with ggplot2?

2
  • 6
    See also this answer, the current solution is to add theme(panel.background = element_rect(fill = "transparent", colour = NA), plot.background = element_rect(fill = "transparent", colour = NA)) Commented Feb 15, 2017 at 14:30
  • Please consider marking the second answer (by YRC) as accepted due to 'opts' being obsolete. Commented May 13, 2018 at 3:37

6 Answers 6

114

Create the initial plot:

library(ggplot2)
d <- rnorm(100)
df <- data.frame(
  x = 1,
  y = d,
  group = rep(c("gr1", "gr2"), 50)
)
p <- ggplot(df) + stat_boxplot(
  aes(
    x = x,
    y = y,
    color = group
  ), 
  fill = "transparent" # for the inside of the boxplot
)

The fastest way to modify the plot above to have a completely transparent background is to set theme()'s rect argument, as all the rectangle elements inherit from rect:

p <- p + theme(rect = element_rect(fill = "transparent"))
          
p

A more controlled way is to set theme()'s more specific arguments individually:

p <- p + theme(
  panel.background = element_rect(fill = "transparent",
                                  colour = NA_character_), # necessary to avoid drawing panel outline
  panel.grid.major = element_blank(), # get rid of major grid
  panel.grid.minor = element_blank(), # get rid of minor grid
  plot.background = element_rect(fill = "transparent",
                                 colour = NA_character_), # necessary to avoid drawing plot outline
  legend.background = element_rect(fill = "transparent"),
  legend.box.background = element_rect(fill = "transparent"),
  legend.key = element_rect(fill = "transparent")
)

p

ggsave() offers a dedicated argument bg to set the

Background colour. If NULL, uses the plot.background fill value from the plot theme.

To write a ggplot object p to filename on disk using a transparent background:

ggsave(
  plot = p,
  filename = "tr_tst2.png",
  bg = "transparent"
)
5
  • 2
    If you don't set the plot.background color like the answer above your plot will have a faint outline.
    – jsta
    Commented Mar 15, 2018 at 22:15
  • 1
    Ahhh... spent too much time on not knowing last step. Saving file with , bg = "transparent".
    – John T
    Commented Sep 25, 2020 at 18:57
  • I cannot believe in 2022 that ggsave is in inches and not pixels. Commented Jan 29, 2022 at 20:26
  • @jsta It's not plot.background but panel.background where you need to set colour = NA.
    – Salim B
    Commented Jun 3, 2022 at 20:40
  • Addendum: My mistake, it needs to be set on both.
    – Salim B
    Commented Jun 3, 2022 at 20:54
93

There is also a plot.background option in addition to panel.background:

df <- data.frame(y=d,x=1)
p <- ggplot(df) + stat_boxplot(aes(x = x,y=y)) 
p <- p + opts(
    panel.background = theme_rect(fill = "transparent",colour = NA), # or theme_blank()
    panel.grid.minor = theme_blank(), 
    panel.grid.major = theme_blank(),
    plot.background = theme_rect(fill = "transparent",colour = NA)
)
#returns white background
png('tr_tst2.png',width=300,height=300,units="px",bg = "transparent")
print(p)
dev.off()

For some reason, the uploaded image is displaying differently than on my computer, so I've omitted it. But for me, I get a plot with an entirely gray background except for the box part of the boxplot which is still white. That can be changed using the fill aesthetic in the boxplot geom as well, I believe.

Edit

ggplot2 has since been updated and the opts() function has been deprecated. Currently, you would use theme() instead of opts() and element_rect() instead of theme_rect(), etc.

4
  • I wasn't expecting it to work with a Mac when tested with that platform's current PowerPoint but it works as advertised. And it works with pdf's as well if you remove the units and substitute sizes in inches Good job.
    – IRTFM
    Commented Sep 17, 2011 at 16:43
  • 1
    This works excellent with MS Powerpoint 2010. Actually, I needed it right for this purpose. Commented Sep 18, 2011 at 14:11
  • 16
    If you're using ggsave, don't forget to add in bg = "transparent" to pass to the png graphics device.
    – Tom
    Commented May 3, 2012 at 7:31
  • 16
    if you're using the knitr package (or slidify etc) you need to pass dev.args = list(bg = 'transparent') as a chunk option. More detail here stackoverflow.com/a/13826154/561698
    – Andrew
    Commented Apr 24, 2014 at 19:50
6

Just to improve YCR's answer:

1) I added black lines on x and y axis. Otherwise they are made transparent too.

2) I added a transparent theme to the legend key. Otherwise, you will get a fill there, which won't be very esthetic.

Finally, note that all those work only with pdf and png formats. jpeg fails to produce transparent graphs.

MyTheme_transparent <- theme(
    panel.background = element_rect(fill = "transparent"), # bg of the panel
    plot.background = element_rect(fill = "transparent", color = NA), # bg of the plot
    panel.grid.major = element_blank(), # get rid of major grid
    panel.grid.minor = element_blank(), # get rid of minor grid
    legend.background = element_rect(fill = "transparent"), # get rid of legend bg
    legend.box.background = element_rect(fill = "transparent"), # get rid of legend panel bg
    legend.key = element_rect(fill = "transparent", colour = NA), # get rid of key legend fill, and of the surrounding
    axis.line = element_line(colour = "black") # adding a black line for x and y axis
)
1

The Cairo package can be used to save ggplots as images with transparent backgrounds. https://cran.r-project.org/web/packages/Cairo/Cairo.pdf

CairoPNG(filename = "TEST.png", bg = "transparent")

ggplot(mtcars, aes(wt, mpg))+
   geom_point()+
   theme(panel.background = element_rect(fill = "transparent"),
      plot.background = element_rect(fill = "transparent", colour = NA))

dev.off()
1
  • Note the typo on "CaiorPNG" (r ill-located). Commented Aug 23, 2022 at 18:48
0

As for someone don't like gray background like academic editor, try this:

p <- p + theme_bw()
p
1
  • 3
    theme_bw gives a white background, not a transparent background. Commented Jan 13, 2021 at 5:00
0

I believe this will work for those who are working within R Markdown and don't want to use ggsave to save a separate file.

You do the following, and just add this chunk option: {r, dev.args = list(bg = 'transparent')}:

ggplot(mtcars, aes(wt, mpg)) +
   geom_point() +
   theme(
     # makes background transparent:
     plot.background = element_rect(fill = "transparent",colour = NA),
     # gets rid of white border around plot: 
     panel.border = element_blank() 
   )

For example, I am using ioslides presentation within R Markdown, though note that I have not tested this outside of this context.

Not the answer you're looking for? Browse other questions tagged or ask your own question.