margin text when combining multiple plots into one - r

I have a series of plots that I want to combine into one, and I cannot use facet_wrap. So each of my plots is a separate object. I want them all the same size, and I can combine them this way.
p = ggplot(mtcars, aes(x=wt, y=mpg)) + geom_point() + xlab("") + ylab("")
g=ggpubr::ggarrange(p, p, p,
p, p, p,
p, p, p,
ncol = 3, nrow = 3)
I want to add some text labels that would apply to the columns and rows, as shown here.
I have tried adding titles to the individual plots (for example, those on the top row), but that reduces the size of the (grayed) plot compared to the others so that the plot dimensions are no longer all the same size.
Any clues would be greatly appreciated.

You can add secondary axes, clear the title for the primary ones and delete the tick marks for secondary ones but keep the titles (look into the theme function I added to your ggplot object). Then tile of those secondary axes can be used to write your desired text. Look below for an example.
library(ggplot2)
library(ggpubr)
p <- ggplot(mtcars, aes(x=wt, y=mpg)) +
geom_point() +
xlab("") + ylab("") +
scale_y_continuous(position = 'right', sec.axis = dup_axis()) +
scale_x_continuous(position = "top", sec.axis = dup_axis()) +
theme(plot.title = element_text(hjust=0.5),
axis.text.x.top = element_blank(),
axis.ticks.x.top = element_blank(),
axis.text.y.right = element_blank(),
axis.ticks.y.right = element_blank(),
axis.title.x.bottom = element_blank(),
axis.title.y.left = element_blank())
ggarrange(p + xlab("some text 1"),
p + xlab("some text 2"),
p + xlab("some text 3") + ylab("some text 33"),
p, p, p + ylab("some text44"),
p, p, p + ylab("some text55"),
ncol = 3, nrow = 3)
You can add axis.title.y.right = element_text(angle = 0) into theme to make y-axis title to be horizontal.
In reference to How to keep axis labels in one side and axis title in another using ggplot2

Related

R | ggplot2 | (remove tick marks + remove panel border) but keep axis lines

novice user here so please be kind and gentle! :)
I am dealing with the following dataset and R script:
#Create pvalue ranges
pvalue <- c(".000 - .005",".005 - .010",".010 - .015",".015 - .020",".020 - .025",".025 - .030",".030 - .035",".035 - .040",".040 - .045",".045 - .050")
#Create frequency counts
count <- c(5000,4000,3100,2540,2390,2260,2150,2075,2050,2025)
dat <- data.frame(pvalue = pvalue, count = count)
#Create plot
myPlot <- ggplot(data=dat, aes(x=pvalue, y=count, group=1)) +
geom_line() +
geom_point() +
geom_vline(xintercept=which(dat$pvalue == '.045 - .050'), linetype = "dashed") +
theme_bw() +
theme(axis.text.x = element_text(angle=90),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank()) +
theme(panel.border = element_blank()) +
ggtitle(paste("Insert Plot Title Here")) +
labs(x = "insert x-axis title here", y = "insert y-axis title here") +
theme(plot.title = element_text(lineheight=0.5,family = "TNR")) +
theme(axis.line.x = element_line(color="black"),
axis.line.y = element_line(color="black")) +
scale_y_discrete(breaks=NULL)
myPlot
The above dataset and R script produce the following plot:
Note that I do not have enough "points" to embed an image so a link to the image has been created by Stack Overflow
An inspection of the image reveals that the left panel border (or the vertical axis) is missing. I want the left panel border to be included in the plot. However, I want to exclude the tick marks on the left panel border (or the vertical axis). Taken together, my desired plot would
include a vertical line for the y-axis,
include a horizontal line for the x-axis,
remove tick marks along the y-axis (vertical axis)
remove the top panel border
remove the right panel border
The above R script takes care of #2-5 in this list. However, I have tried and tried and am unable to figure out how to take care of #1 in this list -- despite including the following in my R script:
theme(axis.line.x = element_line(color="black"),
axis.line.y = element_line(color="black")) +
Can somebody help me to produce the desired image? Very much appreciated :)
The scale_y_discrete(breaks = NULL) breaks the y axis, as it interpret as show nothing.
Removing that line we have the y axis and we can then remove ticks and text:
library(ggplot2)
ggplot(data=dat, aes(x=pvalue, y=count, group=1)) +
geom_line() +
geom_point() +
geom_vline(xintercept=which(dat$pvalue == '.045 - .050'), linetype = "dashed") +
ggtitle(paste("Insert Plot Title Here")) +
labs(x = "insert x-axis title here", y = "insert y-axis title here") +
theme_bw() +
theme(plot.title = element_text(lineheight=0.5,family = "TNR"),
axis.line = element_line(),
axis.ticks.y = element_blank(), ## <- this line
axis.text.y = element_blank(), ## <- and this line
axis.text.x = element_text(angle=90),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
panel.border = element_blank())

Adding a single legend with very long text to a ggplot2 facet_grid

Using R ggplot2 library, I an generating a facet_grid plot and I want to put a legend off to the right hand side of all the plots -NOT EACH INDIVIDUAL PLOT, but one legend that works for all the plots
g = ggplot(pd2, aes(x = p/1000, y=c/1000 )) +
geom_point(alpha=.1, colour="red") +
geom_smooth(method=lm) +
xlab("Ave P") +
ylab("Ave C)") +
labs(title = "Comparison ") +
theme(plot.title = element_text(face="bold",
size=14, colour="black", hjust = 0.5)) +
theme(axis.title = element_text(face="bold", size=12, colour="blue")) +
facet_grid(code ~ TheState) +
theme(strip.text.y = element_text(colour = "purple", angle = 0,
size = 9, hjust = 0.5, vjust = 0.5))
What I want to do is have a legend off to the right that is turned 90 degrees - because I want the legend to refer to very_long_code instead of just "code." I've tried all kinds of variations of legend, theme, and guide. Intuitively, I would like to say,
legend(text, angle=90, very_long_code, color="purple")
The next step would be to not use a single color, but to use a different color for each one that would correspond to colors in the strip.

ggplot2 align top of two facetted plots

I need to arrange two faceted graphs, like so:
d = data.frame(Index = LETTERS[1:5],x=1:5,y=1:5)
A = ggplot(subset(d,Index == 'A'),aes(x,y)) +
theme_bw() +
theme(axis.title.x = element_blank()) +
geom_point() + facet_wrap(~Index) + labs(title = "Title, The Title",
subtitle = "Subtitle, The Subtitle",
y = "Side Axes")
B = ggplot(subset(d,Index != 'A'),aes(x,y)) +
theme_bw() +
theme(axis.title.x = element_blank(), axis.title.y = element_blank()) +
geom_point() + facet_wrap(~Index) + labs(title = "", subtitle = "")
g = gridExtra::arrangeGrob(A,B,ncol=2,bottom="Bottom Axes")
grid.arrange(g)
Which produces the following:
As you can see from the above, there is a slight misalignment between the top edges of the plot region. This is caused by the 'commas' in the title and subtitles.
Does anyone know how I can enforce the top edges to align? I need a title and subtitle on the left plot, with an (empty) title, subtitle on the right one.
#CephBirk's solution is a clever and easy way to go here. For cases where a hack like that doesn't work, you can remove the title and sub-title from your plots and instead create separate grobs for them that you can lay out, along with the plots, using grid.arrange and arrangeGrob. In the code below, I've also added a nullGrob() as a spacer between plots A and B, so that the right x-label (1.50) in the left graph isn't cut off.
library(gridExtra)
A = ggplot(subset(d,Index == 'A'),aes(x,y)) +
theme_bw() +
theme(axis.title = element_blank()) +
geom_point() + facet_wrap(~Index)
B = ggplot(subset(d,Index != 'A'),aes(x,y)) +
theme_bw() +
theme(axis.title.x = element_blank(), axis.title.y = element_blank()) +
geom_point() + facet_wrap(~Index)
grid.arrange(
arrangeGrob(
arrangeGrob(textGrob("Title, The Title", hjust=0),
textGrob("Subtitle, The Subtitle", hjust=0, gp=gpar(cex=0.8))),
nullGrob(), ncol=2, widths=c(1,4)),
arrangeGrob(A, nullGrob(), B, ncol=3, widths=c(8,0.1,8),
left="Side Axes", bottom="Bottom Axes"),
heights=c(1,12))
It's a bit hackish, but you can have the same title and subtitle on the right as the left but print it in white font. :) You said it's due to the commas, so that fixes it.
Not the most satisfying, but it gets the job done.
B = ggplot(subset(d,Index != 'A'),aes(x,y)) +
theme_bw() +
theme(axis.title.x = element_blank(), axis.title.y = element_blank(), title = element_text(color = 'white')) +
geom_point() + facet_wrap(~Index) +
labs(title = "Title, The Title", subtitle = "Subtitle, The Subtitle")
egg::ggarrange(A, B, ncol=2, bottom="Bottom Axes")

Moving facet labels that have two lines near the plotting area

I’m working with faceted plots and I’m having an issue trying to move facet labels that have two lines near the plotting area.
Consider the minimal example:
require(ggplot2)
labs <- as_labeller(c(`0` = "LABEL 1",
`1` = "LABEL 2 HAS TWO LINES\nBECAUSE IT'S TOO LONG"))
p <- ggplot(mtcars, aes(disp, drat)) +
geom_point() +
theme_bw() +
geom_hline(yintercept=2, linetype="solid") +
geom_vline(xintercept=50, linetype="solid") +
scale_x_continuous(limits=c(50,500), expand =c(0,0)) +
scale_y_continuous(limits = c(2, 5), expand = c(0,0)) +
theme(panel.border = element_blank(),
strip.background = element_blank(),
strip.text = element_text(size=9),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank()) +
facet_wrap(~am, labeller = labs)
p
Now adding vjust=-0.62 to move the facet labels near the plotting area we have the following:
p + theme(strip.text = element_text(size=9, vjust=-0.62))
As you can see only LABEL 1, the single line label, is moved close to the plotting area - and that’s the problem.
I wished that both labels could have moved. Does anyone have any suggestion?
*Observation: I’m working with a considerable amount of faceted plots so making and customizing plots one-by-one doesn’t seem to be a good idea.
Hope this may helpful for you
p + theme(strip.text = element_text(size=9, vjust=1))

Space between gpplot2 horizontal legend elements

I have a ggplot2 plot as follows:
library(ggplot2)
ggplot(mtcars, aes(factor(cyl), fill=factor(cyl))) +
geom_bar() +
coord_flip() +
theme(legend.position = 'top') +
guides(fill = guide_legend(title=NULL))
I'd like add spacing between the fill elements as follows:
The issue mentioned by alistaire and Tyler Rinker was solved. Now we can adjust the margins of the element_text`.
ggplot(mtcars, aes(factor(cyl), fill = factor(cyl))) +
geom_bar() +
coord_flip() +
theme(
legend.position = 'top',
legend.title = element_blank(),
legend.text = element_text(margin = margin(r = 2, unit = 'cm'))
)
It really seems something like theme(legend.text = element_text(margin = margin(r = 2, unit = 'in'))) would be the right way to accomplish the task, but that doesn't do anything at all.
Instead, (and not for the first time) I fall back on the Microsoft Word style of alignment-hacking, i.e. just add spaces:
ggplot(mtcars, aes(factor(cyl), fill=factor(paste(cyl, ' ')))) +
geom_bar() +
coord_flip() +
theme(legend.position = 'top') +
guides(fill = guide_legend(title=NULL))
Because there's spaces on the 8 as well, it's a little off-center, but if you just paste them onto the previous labels you can nudge them around as you like.
Apologies for any nightmares caused to graphic designers.
This is another hack but one that I prefer, as it adds additional white space at the end of each label according to its number of characters. Replace fill = factor(cyl) with
fill = sprintf("%-20s", factor(cyl)).
This pads all strings in the vector with white characters on the right to reach 20 characters total. This is perfect if you have text labels of different lengths. You can change 20 to whatever number you want, or remove the negative sign to add spaces to the left instead of the right. In general sprintf() is a good function to explore and use for formatting text and numbers as desired.
This is a hack, but...
Let's add some empty factor levels in cyl between the real levels. Then we'll make sure they're included in the plot (using drop=FALSE) for spacing in the legend, but will set their colors and labels to empty values so that you can't see them in the legend. I found that I also needed to include override.aes=list(color="white") in order to avoid the blank legend key boxes still being ever-so-slightly visible in the legend.
mtcars$cyl = factor(mtcars$cyl, levels=c(4, 11:15, 6, 16:20, 8))
cols = hcl(seq(15,375,length.out=4)[1:3], 100, 65)
ggplot(mtcars, aes(cyl, fill=cyl)) +
geom_bar() +
coord_flip() +
scale_fill_manual(values=c(cols[1], rep("white",5), cols[2], rep("white",5), cols[3]),
labels=c(4, rep("",5), 6, rep("",5), 8), drop=FALSE) +
theme(legend.position = 'top') +
guides(fill = guide_legend(title=NULL, nrow=1, override.aes=list(color="white")))
With ggplot2 v3.0.0, we can use legend.spacing.x to manipulate the space between legend keys.
library(ggplot2)
ggplot(mtcars, aes(factor(cyl), fill = factor(cyl))) +
geom_bar() +
coord_flip() +
theme(legend.position = 'top') +
guides(fill = guide_legend(title = "Cyl")) +
theme(legend.spacing.x = unit(0.5, 'cm'))
Created on 2018-05-30 by the reprex package (v0.2.0).
Not a hack here, this is the way to do it:
Use theme(legend.text = element_text(margin = margin(r = 2, unit = 'cm')))
ggplot(mtcars, aes(factor(cyl), fill = factor(cyl))) +
geom_bar() +
coord_flip() +
theme(
legend.position = 'top',
legend.title = element_blank(),
legend.text = element_text(margin = margin(r = 2, unit = 'cm'))
)
Will do it.

Resources