Saving a dark-themed plot using ggsave() creates white bordering panels - r

I need my charts to have a dark gray theme to match a presentation style. I also need them to be fixed height, but the widths may vary depending on the length of the labels on the y-axis. When I try to export or save, there are always white side bars in the .jpg or .png file.
Here's some sample code that I use to create the chart (there are some extra theming controls in here that are superfluous to the simplified example, but the resulting chart is basically what I am generating):
library(ggplot2)
bar.font <- 8
title <- "Example"
l_labs <- c("")
x_labs <- c("A","B","C")
ests <- c(.5,.3,.2)
nerrs <- c(.05, .05, .05)
perrs <- nerrs
barchart.data <- data.frame(l_labs, x_labs, ests, nerrs, perrs)
p <- ggplot(barchart.data, aes(x=x_labs, y=ests*100)) +
geom_bar(stat="identity", color="#808080", position=position_dodge(), width=0.85, fill="#808080") +
geom_text(aes(y=ests*100+perrs*100+1.5, label=sprintf("%1.1f%%", 100*ests)), vjust=0.5, hjust=0, size=bar.font, color="white") +
geom_errorbar(aes(ymin=ests*100-nerrs*100, ymax=ests*100+perrs*100), width=.2, position=position_dodge(.9), color="white", size=0.25) +
labs(title=title, x="", y = "") + theme_classic() +
scale_y_continuous(expand = c(0,0),limits = c(0,115), breaks=c(0, 20, 40, 60, 80, 100)) +
theme(legend.position="none", legend.text = element_text(color = "white")) +
theme(title = element_text(size=18, colour = "white")) +
theme(axis.text = element_text(size=20, color = "white"), axis.line = element_line(color = "white")) +
theme(axis.text.x = element_text(margin=margin(9,0,0,0)),axis.text.y = element_text(margin=margin(0,9,0,0))) +
theme(axis.title = element_text(size=20, color = "white")) +
theme(axis.title.x = element_text(margin = margin(10,0,0,0))) +
theme(axis.ticks = element_line(colour = 'white', size = .5)) +
coord_flip() +
theme(aspect.ratio = 1) +
theme(panel.background = element_rect(fill = "#1e1e1e")) +
theme(legend.justification=c(1,0), legend.position=c(1,0)) +
theme(plot.background = element_rect(fill = "#1e1e1e", color = "#1e1e1e")) +
theme(panel.grid.major.x = element_line(colour = "white",size=0.1, linetype = "dotted"))
ggsave("test.jpg", height=10, units="in")
And here is what the exported .jpg looks like. I cannot specify an exact width because I do not know what it will be for each chart as the widths vary. Thanks for any guidance.

You can set the background color to whatever value you like:
ggsave("test.jpg", height=10, units="in", bg = "#1e1e1e")
This takes care of the white bars.
It may be a bit confusing that the bg option is not mentioned in the ggsave() documentation. That's because it's part of the graphics device, here jpeg(). It is mentioned in the jpeg() documentation.
The reason why there are white bars in the first place is discussed in depth in this post.

Related

R ggplot geom_text wipes out background--bug?

I found an issue with ggplot2::geom_text() when I attempt to highlight my data with labels. My MWE illustrates the situation. After I define the plot I add the theme() from phase#1 which colors the panel and plot backgrounds. The red/green is for emphasis. When the labels are added in phase#2, the plot.background goes to white and the panel background to the default grey. Is this something I'm doing, is this an undocumented feature of ggplot2, or is this a bug?
require(ggplot2)
SESnow <- data.frame(Year=c(1978,1988,1995,2000,2013,2017),
Snow=c(355.9,322.1,329.1,303.6,318.5,304.0))
p <- ggplot(SESnow, aes(x=Year, y=Snow, fill=Snow)) +
geom_col(width=1) +
scale_fill_gradient(low="blue", high="red", limits=c(0,400)) +
theme(axis.title.y=element_text(angle=0)) +
ggtitle("Yearly Total Snowfall (inch)") +
labs(subtitle = "Copper City 2019",
caption="Source: Keweenaw County",
x="Snow Season") +
theme(legend.position="none")
#phase#1
p + theme( panel.background = element_rect(fill = "green",
colour = "black",
size = 0.5, linetype = "solid"),
plot.background = element_rect(fill = "blue",
colour = "black",
size = 0.5, linetype = "solid"),
axis.text.x = element_text(colour="grey20",size=11, vjust=1,
margin=margin(t=0,b=0),face="bold"),
axis.text.y = element_text(colour="grey20",size=11, hjust=1,
margin=margin(t=10,b=10),face="bold") )
#phase#2
p + geom_text(data=SESnow, aes(label = Snow, fill=NULL ), y = SESnow$Snow + 20.0,
label=format(SESnow$Snow, digits=2), size=3, fontface="bold",
color="black")
Also note that if you run phase#1 after phase#2 the labels disappear, so this feature is consistent. How do I get a plot with labels and colored background?
The answer is simple. You are generating two plots instead of one. You need to store the plot in p if you want to use the same plot and modify it later.
#phase#1
p <- p + theme( panel.background = element_rect(fill = "green",
colour = "black",
size = 0.5, linetype = "solid"),
plot.background = element_rect(fill = "blue",
colour = "black",
size = 0.5, linetype = "solid"),
axis.text.x = element_text(colour="grey20",size=11, vjust=1,
margin=margin(t=0,b=0),face="bold"),
axis.text.y = element_text(colour="grey20",size=11, hjust=1,
margin=margin(t=10,b=10),face="bold") )
#phase#2
p + geom_text(data=SESnow, aes(label = Snow, fill=NULL ), y = SESnow$Snow + 20.0,
label=format(SESnow$Snow, digits=2), size=3, fontface="bold",
color="black")
Assign the value to p before you use it again. This will solve the issue.
Edit: I am attaching the graph. I guess this is what you wanted.

Export from ggplot2 dark theme with no white border?

I want my plots to have dark background to match a slide theme that I am using. I have everything the way I want it, but I cannot figure out how to remove the white border from the overall image. I am looking for something like theme(plot.border = element_line(color = "#1e1e1e")) but there does not seem to be a plot.border attribute.
No matter what I do to my export size, it always includes it. I never even knew there was a border in the past because I was always using white on white, but now it is revealed!
I've tried a bunch of stuff and cannot get rid of that stupid line, and I really don't want to have to crop my images to remove, or take manual screenshots from RStudio :)
Here's the code, and see below for the image it's creating...
p<- ggplot(barchart.data, aes(x=x_labs, y=ests, fill=l_labs)) +
geom_bar(stat="identity", color=fill_colors, position=position_dodge(), fill=fill_colors) +
geom_text(aes(y=ests+perrs+0.02, label=sprintf("%1.1f%%", 100*ests)), vjust=0.5, hjust=0, size=bar.font, color="white") +
geom_errorbar(aes(ymin=ests-nerrs, ymax=ests+perrs), width=.2, position=position_dodge(.9), color="white", size=0.25) +
labs(title=chtit, x=xaxis, y = yaxis) +
theme_classic() +
scale_y_continuous(limits = c(0,1.1), breaks=c(0, 0.2, 0.4, 0.6, 0.8, 1)) +
theme(legend.position="none", legend.text = element_text(color = "white")) +
theme(title = element_text(colour = "white")) +
theme(axis.text = element_text(size=12, color = "white"), axis.line = element_line(color = "white")) +
theme(axis.title = element_text(size=12, color = "white")) +
coord_flip() +
theme(panel.grid.major.x = element_line(colour = "white",size=0.25))+
theme(aspect.ratio = 1) +
theme(panel.background = element_rect(fill = "#1e1e1e")) +
theme(plot.background = element_rect(fill = "#1e1e1e")) +
guides(fill = guide_legend(reverse = TRUE))
return(p)

move legend title in ggplot2

I have been trying to shift my legend title across to be centered over the legend contents using the guide function. I've been trying to use the following code:
guides(colour=guide_legend(title.hjust = 20))
I thought of trying to make a reproducable example, but I think the reason it's not working has something to do with the above line not matching the rest of my code specifically. So here is the rest of the code I'm using in my plot:
NH4.cum <- ggplot(data=NH4_by_Date, aes(x=date, y=avg.NH4, group = CO2, colour=CO2)) +
geom_line(aes(linetype=CO2), size=1) + #line options
geom_point(size=3) + #point symbol sizes
#scale_shape_manual(values = c(1, 16)) + #manually choose symbols
theme_bw()+
theme(axis.text.x=element_text(colour="white"), #change x axis labels to white.
axis.title=element_text(size=12),
axis.title.x = element_text(color="white"), #Change x axis label colour to white
panel.border = element_blank(), #remove box boarder
axis.line.x = element_line(color="black", size = 0.5), #add x axis line
axis.line.y = element_line(color="black", size = 0.5), #add y axis line
legend.key = element_blank(), #remove grey box from around legend
legend.position = c(0.9, 0.6))+ #change legend position
geom_vline(xintercept=c(1.4,7.5), linetype="dotted", color="black")+ #put in dotted lines for season boundaries
scale_color_manual(values = c("#FF6600", "green4", "#0099FF"),
name=expression(CO[2]~concentration~(ppm))) + #manually define line colour
scale_linetype_manual(guide="none", values=c("solid", "solid", "solid")) + #manually define line types
scale_shape_manual(values = c(16, 16, 16)) + #manually choose symbols
guides(colour=guide_legend(title.hjust = 20))+
scale_y_continuous(expand = c(0, 0), limits = c(0,2200), breaks=seq(0,2200,200))+ #change x axis to intercept y axis at 0
xlab("Date")+
ylab(expression(Membrane~available~NH[4]^{" +"}~-N~(~mu~g~resin^{-1}~14~day^{-1})))+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
geom_errorbar(aes(ymin = avg.NH4 - se.NH4, #set y error bars
ymax = avg.NH4 + se.NH4),
width=0.1)
I have tried doing the following instead with no luck:
guides(fill=guide_legend(title.hjust=20)
I have also adjusted the hjust value from values between -2 to 20 just to see if that made a difference but it didn't.
I'll try to attach a picture of the graph so far so you can see what I'm talking about.
I've looked through all the questions I can on stack overflow and to the best of my knowledge this is not a duplicate as it's specific to a coding error of my own somewhere.
Thank-you in advance!!
The obvious approach e.g.
theme(legend.title = element_text(hjust = .5))
didn't work for me. I wonder if it is related to this open issue in ggplot2. In any case, one manual approach would be to remove the legend title, and position a new one manually:
ggplot(mtcars, aes(x = wt, y = mpg, colour = factor(cyl))) +
geom_point() +
stat_smooth(se = FALSE) +
theme_bw() +
theme(legend.position = c(.85, .6),
legend.title = element_blank(),
legend.background = element_rect(fill = alpha("white", 0)),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank()) +
annotate("text", x = 5, y = 27, size = 3,
label = "CO[2]~concentration~(ppm)", parse = TRUE)
Output:

Relative legend position in ggplot

this is my small script in order to make some batch plot in ggplot:
by(database_per_grafici, database_per_grafici$variable, function(i){
ggplot(subset(i, !is.na(value)))+
stat_ecdf(aes(x=value, color=gruppo), size=2)+
scale_y_continuous(labels = percent) +
theme_bw() +
theme(panel.grid.major = element_line(colour = "black", size= 0.3))+
theme(legend.text = element_text(size = 60)) +
theme(legend.justification=c(1,0), legend.position=c(1,0))+
theme(legend.title=element_blank()) +
theme(axis.text.x = element_text(size=16)) +
theme(axis.title.x = element_text(size=20))+
xlab("mg/kg")+
theme(axis.text.y = element_text(size=16)) +
theme(axis.title.y = element_blank()) +
guides(colour = guide_legend(override.aes = list(size=10))) +
ggsave(sprintf("%s.png", unique(i$variable), width = 30,
height = 20, units = "cm"))
})
but there is a problem with the legend as you can see in the two following pictures:
and
the problem is that in some plots, the legend overlays the plot itself.
Is there a way to set the legend position according to the dataframe values?
Thanks

How to change barplot in ggplot for R

I have a plot in ggplot that shows me for each category of "rating" the level of price in "bank" and "sistem". This is my code:
##fict
a<-c("rating1","rating2","rating3")
b<-c(1.2,1.2,1.3)
c<-c(1.6,1.4,1.6)
gg<-cbind('rating'=rep(a,2),'price'=c(b,c),'tipo'=rep(c("bank","sistem"),3))
gg<-as.data.frame(gg)
a<-rgb(red=150, green=191, blue=37, maxColorValue = 255)
b<-rgb(red=80, green=113, blue=14, maxColorValue = 255)
ggplot(gg, aes(x=tipo, y=price,width=1)) +
geom_bar(position='stack', stat='identity', fill=c(b,a), color='black') +
facet_wrap( ~ rating)+
theme_bw() + theme(axis.line = element_line(colour = "black"),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
panel.background = element_blank(),
strip.background = element_rect(colour = 'white', fill = 'white', size = 3),
axis.title.y=element_text(vjust=0.19),
axis.title.x=element_text(vjust=0.19)
#strip.text.x = element_text(colour = 'red', angle = 45, size = 10, hjust = 0.5, vjust = 0.5, face = 'bold')
) + xlab("My x label") +
ylab("My y label") +
labs(title = 'difference')
This code generates my plot.
I'd like to change 3 things:
I'd like that the labels rating shows in the bottom
I'd like that the "bank" and "sistem" labels disappear and change it with the legend with colors for bank and sistem.
If it's possible also put the legend under the x-axis title in horizontal way
Thank you
Upgrade comment to an answer.
library(ggplot2)
# your data - tweaked the code - there is no need to cbind within data.frame
# and names do not need to be in quotes
gg <- data.frame(rating=rep(c("rating1","rating2","rating3"),2),
price=c(c(1.2,1.2,1.3),c(1.6,1.4,1.6)),
tipo=rep(c("bank","sistem"),3))
a <- rgb(red=150, green=191, blue=37, maxColorValue = 255)
b <- rgb(red=80, green=113, blue=14, maxColorValue = 255)
# Plot
# use position dodge to get the bars side-by-side
# theme_classic removes grid lines and uses theme_bw()
# scale_fill_manual to manually specify the colours - by using fill = tipo in the
# aesthetic call of ggplot a legend will be generated
# scale_y_continuous - using expand starts the axis at exactly zero
ggplot(gg, aes(x=rating, y=price, fill=tipo)) +
geom_bar(position='dodge', stat='identity', color='black') +
theme_classic() +
scale_fill_manual(values = c(b,a)) +
scale_y_continuous(limit=c(0,2), expand=c(0,0)) +
labs(title = 'difference', x = "My x label", y = "My y label") +
theme(
axis.title.y=element_text(vjust=0.19),
axis.title.x=element_text(vjust=0.19) ,
legend.position = "bottom",
legend.title=element_blank())

Resources