Multi-line legend text including exponent with ggplot - r

With ggplot, I want to add a left aligned legend title with multiple lines and exponents in the text for the units of the values in the legend. I'm plotting data of a form similar to:
leakage_rates_levels <- c(5.4, 0.25)
leakage_rates <- as.factor(rep(leakage_rates_levels, 3)) # L/s-m^2 at 75 Pa
data_groups_levels <- c('Set 1', 'Set 2', 'Set 3')
data_groups <- as.factor(rep(data_groups_levels, each=2))
moisture_level <- c(7, 3, 11, 10, 16, 6)
plotdt <- data.frame(data_groups, leakage_rates, moisture_level)
I use expression() to add exponents to the units in the legend. The following code generates the desired figure, but with the legend title text mis-formatted.
ggplot(plotdt, aes(data_groups)) +
geom_bar(aes(weight=moisture_level, fill=leakage_rates), position='dodge') +
labs(y='Moisture Level') +
labs(fill=expression(paste('Leakage Rate\nat 75 Pa\n(L/s-', m^2, ')', sep=''))) +
theme(panel.grid.major.x = element_blank(),
axis.title.x = element_blank())
The legend title appears left aligned except for the final line, which has a bunch of extraneous spaces in the middle of it.
Using legend_title_align=0 (suggested here) and/or legend_title=element_text(hjust=1) in theme() have no effect. Trying to add phantom() spacing also did not work (suggested here). The end of the top answer to this question notes the same problem I'm encountering but does not propose a solution.
Is there a way to get the meter squared term in the legend to be left-aligned like the rest of the text?
I am using ggplot 3.1.0 and R 3.5.1.

You can use the unicode representation of superscript two (U+00B2) and avoid the
problem-causing combination of expression() and a multi-line legend title:
ggplot(plotdt, aes(data_groups)) +
geom_bar(aes(weight=moisture_level, fill=leakage_rates), position='dodge') +
labs(y='Moisture Level') +
labs(fill=paste('Leakage Rate\nat 75 Pa\n(L/s-m\u00b2)', sep='')) +
theme(panel.grid.major.x = element_blank(),
axis.title.x = element_blank())

You can use atop to have lines "atop" each other.
Because you have 3 lines and atop only accepts 2 arguments however, you need to have 2 atop nested in one another. This makes the font on some of the lines smaller. The way to prevent this is to pass the expressions to either textstyle or displaystyle:
ggplot(plotdt, aes(data_groups)) +
geom_bar(aes(weight = moisture_level, fill = leakage_rates), position = "dodge") +
labs(y = "Moisture Level") +
labs(fill = expression(atop(atop(textstyle("Leakage Rate"),
textstyle("at 75 Pa")),
"(L/s-" ~m^2~ ")"))) +
theme(panel.grid.major.x = element_blank(), axis.title.x = element_blank())

Related

Concat math symbols and strings in ggplot2 labels - R, LaTex Solution?

I am trying to label the y-axis of my graph with the Theta greek symbol and P(z) with a comma separating them. Additionally, I am tyring to label my x-axis Q(z_i) where i is a subscript. I have tried to do this a few different ways..
string <- ", P(z)"
thet <- bquote(theta)
ylab.fig2 <- paste(thet, string, sep = "")
and have done something similar with expression(theta). I use ylab.fig2 as an input in my ggplot, ylab(fig.2).
new <- ggplot(data = data.frame(x=0), aes(x=x)) +
stat_function(fun=Pz.eq, aes(colour="P(z)")) +
stat_function(fun=bid1, aes(colour="Bid Curve: House 1")) +
stat_function(fun=bid2, aes(colour="Bid Curve: House 2")) +
stat_function(fun=bid3, aes(colour="Bid Curve: House 3")) +
xlim(0,20) + ylim(0,6) +
xlab("Q(z_i)") + ylab(ylab.fig2) +
ggtitle("Figure 2: Property Choice Per Household") +
theme(panel.grid = element_blank(),
axis.text.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.x = element_blank(),
axis.ticks.y = element_blank(),
legend.title = element_blank(),
plot.title = element_text(hjust=0.5)) +
scale_colour_manual("Groups",
values = c("darkseagreen", "darkkhaki", "darkslategray3", "firebrick"))
The bquote() and expression() both work fine if they are sole inputs but when I use paste to return the rest of the axis label the greek symbol is not output. I believe this is due to the differing class() of each object. Alternatively, if there is a way to compile LaTex in the labels that would solve both my x and y-axis issues.
This is what my graph looks like thus far...
Overall, there are three things I'm trying to accomplish with x and y-axis labels:
1) Concat greek letters with text.
2) Put bold text inside of the label (only the z vector in P(z) will be bold).
3) Place 'i' subscripts on my text.
While the question regarding Greek letters has been posted before I am looking for a solution using LaTex where I can use more than just math symbols. Using LaTex code is will allow me to solve issues 2 and 3, not just 1.
The latex2exp package is probably the easiest:
library(latex2exp)
string <- ", P(z)"
thet <- "$\\theta$"
ylab.fig2 <- TeX(paste(thet, string, sep = ""))
And then use as ... + ylab(ylab.fig2) to build the plot.
Or using bquote and expression:
library(ggplot2)
i=2
f <- bquote(expression(theta * ", " * P(bold(z))))
g <- bquote(expression(Q(z[.(i)])))
ggplot(mtcars, aes(x=hp, y=wt)) + geom_point()+
ylab(eval(f))+
xlab(eval(g))

Increase the distance between x axis factor and the plot [duplicate]

The y-axis title appears too close to the axis text.
ggplot(mpg, aes(cty, hwy)) + geom_point()
I have tried changing the value of many parameters with theme() but none seems to help.
From ggplot2 2.0.0 you can use the margin = argument of element_text() to change the distance between the axis title and the numbers. Set the values of the margin on top, right, bottom, and left side of the element.
ggplot(mpg, aes(cty, hwy)) + geom_point()+
theme(axis.title.y = element_text(margin = margin(t = 0, r = 20, b = 0, l = 0)))
margin can also be used for other element_text elements (see ?theme), such as axis.text.x, axis.text.y and title.
addition
in order to set the margin for axis titles when the axis has a different position (e.g., with scale_x_...(position = "top"), you'll need a different theme setting - e.g. axis.title.x.top. See https://github.com/tidyverse/ggplot2/issues/4343.
Based on this forum post: https://groups.google.com/forum/#!topic/ggplot2/mK9DR3dKIBU
Sounds like the easiest thing to do is to add a line break (\n) before your x axis, and after your y axis labels. Seems a lot easier (although dumber) than the solutions posted above.
ggplot(mpg, aes(cty, hwy)) +
geom_point() +
xlab("\nYour_x_Label") + ylab("Your_y_Label\n")
A solution that offers more fine-grained control than \n but is less cumbersome than adding margins is to use vjust in the theme function.
For adjusting the position on the y-axis or (x-axis) to add space, this often requires using a positive value for vjust (y-axis) or a negative value for vjust (x-axis) as in theme(axis.title.y = element_text(vjust = 2)). See a fully worked example below.
# load patchwork to show plots side-by-side
library(patchwork)
library(ggplot2)
# Plot A: just for comparison, moving titles *inward*
p1 <- ggplot(mpg, aes(cty, hwy)) +
geom_point() +
theme_gray() +
theme(
axis.title.y = element_text(vjust = -3),
axis.title.x = element_text(vjust = +3)
)
# Plot B: what we want, moving titles *outward*
p2 <- ggplot(mpg, aes(cty, hwy)) +
geom_point() +
theme_gray() +
theme(
axis.title.y = element_text(vjust = +3),
axis.title.x = element_text(vjust = -0.75)
)
# show plots side-by-side with patchwork package
p1 + p2 +
plot_annotation(tag_levels = "A")
For some reason the margin argument suggested by Didzis Elferts did not work for me. So, I used a different hack that is more flexible than adding an empty line but needs giving up the axis ticks.
myplot + theme(axis.ticks.x = element_blank(), axis.ticks.length.x = unit(3.25, "cm")
I guess, one can add the tick marks manually with geom_segment. Another possibility might be [ggalt::annotation_ticks][1]but I didn't bother trying either (note the current version of ggalt on CRAN (0.4) does not support this function, the one on github (0.6) does).

Put legend under each facet using facet_grid; adding one title and one caption to plot

I'm working with a plot analogous to the following:
ggplot(data=mtcars, aes(x=wt, y=mpg, color=carb)) +
geom_line() + facet_grid(gear ~ .) +
ggtitle(expression("Title")) +
labs(caption = "Sources: Compustat, Author's Calculations") +
theme(plot.title = element_text(size = 20, hjust = 0.5),
plot.caption=element_text(size=8, hjust=.5),
strip.background = element_blank(),
strip.text = element_blank(),
legend.title = element_blank())
I'm trying to do the following:
Insert a legend beneath each of the 3 facets, each legend specific to the facet above it.
Insert one plot title (as opposed to the same title above each facet).
Insert one caption beneath the final facet (as opposed to three captions beneath each facet).
I was able to reproduce this example on assigning a legend to each facet.
However, the plot title was placed above and the caption below each facet. Also, this example uses facet_wrap and not facet_grid.
Thank you in advance.
library(dplyr)
library(ggplot2)
tempgg <- mtcars %>%
group_by(gear) %>%
do(gg = {ggplot(data=., aes(x=wt, y=mpg, color=carb)) +
geom_point() +
labs(x = NULL) +
guides(color = guide_colorbar(title.position = "left")) +
theme(plot.title = element_text(size = 20, hjust = 0.5),
plot.caption=element_text(size=8, hjust=.5),
legend.position = "bottom")})
tempgg$gg[1][[1]] <- tempgg$gg[1][[1]] + labs(title = "Top title")
tempgg$gg[3][[1]] <- tempgg$gg[3][[1]] + labs(x = "Axis label", caption = "Bottom caption")
tempgg %>% gridExtra::grid.arrange(grobs = .$gg)
This isn't the most elegant way to do it. Each of the three grobs gets an equal space when you grid.arrange them, so the first and last ones are squished from the title and caption taking up space. You could add something like heights = c(3,2,3) inside the grid.arrange call, but you'd have to fiddle with each of the heights to get it to look right, and even then it would be a visual approximation, not exact.
To do it the more precise way, you'd need to look at the underlying gtables in each of the grobs. https://stackoverflow.com/users/471093/baptiste is the expert on that.
Update:
I used a #baptiste solution, which is still not particularly elegant, but gives you the same plot space for each panel. Use this snippet in place of the last line above.
tempggt <- tempgg %>% do(ggt = ggplot_gtable(ggplot_build(.$gg))) %>% .$ggt
gg1 <- tempggt[[1]]
gg2 <- tempggt[[2]]
gg3 <- tempggt[[3]]
gridExtra::grid.arrange(gridExtra::rbind.gtable(gg1, gg2, gg3))

Change size of axes title and labels in ggplot2

I have a really simple question, which I am struggling to find the answer to. I hoped someone here might be able to help me.
An example dataframe is presented below:
a <- c(1:10)
b <- c(10:1)
df <- data.frame(a,b)
library(ggplot2)
g = ggplot(data=df) + geom_point(aes(x=a, y=b)) +
xlab("x axis")
g
I just want to learn how I change the text size of the axes titles and the axes labels.
You can change axis text and label size with arguments axis.text= and axis.title= in function theme(). If you need, for example, change only x axis title size, then use axis.title.x=.
g+theme(axis.text=element_text(size=12),
axis.title=element_text(size=14,face="bold"))
There is good examples about setting of different theme() parameters in ggplot2 page.
I think a better way to do this is to change the base_size argument. It will increase the text sizes consistently.
g + theme_grey(base_size = 22)
As seen here.
If you are creating many graphs, you could be tired of typing for each graph the lines of code controlling for the size of the titles and texts. What I typically do is creating an object (of class "theme" "gg") that defines the desired theme characteristics. You can do that at the beginning of your code.
My_Theme = theme(
axis.title.x = element_text(size = 16),
axis.text.x = element_text(size = 14),
axis.title.y = element_text(size = 16))
Next, all you will have to do is adding My_Theme to your graphs.
g + My_Theme
if you have another graph, g1, just write:
g1 + My_Theme
and so on.
To change the size of (almost) all text elements, in one place, and synchronously, rel() is quite efficient:
g+theme(text = element_text(size=rel(3.5))
You might want to tweak the number a bit, to get the optimum result. It sets both the horizontal and vertical axis labels and titles, and other text elements, on the same scale. One exception is faceted grids' titles which must be manually set to the same value, for example if both x and y facets are used in a graph:
theme(text = element_text(size=rel(3.5)),
strip.text.x = element_text(size=rel(3.5)),
strip.text.y = element_text(size=rel(3.5)))

Increase distance between text and title on the y-axis

The y-axis title appears too close to the axis text.
ggplot(mpg, aes(cty, hwy)) + geom_point()
I have tried changing the value of many parameters with theme() but none seems to help.
From ggplot2 2.0.0 you can use the margin = argument of element_text() to change the distance between the axis title and the numbers. Set the values of the margin on top, right, bottom, and left side of the element.
ggplot(mpg, aes(cty, hwy)) + geom_point()+
theme(axis.title.y = element_text(margin = margin(t = 0, r = 20, b = 0, l = 0)))
margin can also be used for other element_text elements (see ?theme), such as axis.text.x, axis.text.y and title.
addition
in order to set the margin for axis titles when the axis has a different position (e.g., with scale_x_...(position = "top"), you'll need a different theme setting - e.g. axis.title.x.top. See https://github.com/tidyverse/ggplot2/issues/4343.
Based on this forum post: https://groups.google.com/forum/#!topic/ggplot2/mK9DR3dKIBU
Sounds like the easiest thing to do is to add a line break (\n) before your x axis, and after your y axis labels. Seems a lot easier (although dumber) than the solutions posted above.
ggplot(mpg, aes(cty, hwy)) +
geom_point() +
xlab("\nYour_x_Label") + ylab("Your_y_Label\n")
A solution that offers more fine-grained control than \n but is less cumbersome than adding margins is to use vjust in the theme function.
For adjusting the position on the y-axis or (x-axis) to add space, this often requires using a positive value for vjust (y-axis) or a negative value for vjust (x-axis) as in theme(axis.title.y = element_text(vjust = 2)). See a fully worked example below.
# load patchwork to show plots side-by-side
library(patchwork)
library(ggplot2)
# Plot A: just for comparison, moving titles *inward*
p1 <- ggplot(mpg, aes(cty, hwy)) +
geom_point() +
theme_gray() +
theme(
axis.title.y = element_text(vjust = -3),
axis.title.x = element_text(vjust = +3)
)
# Plot B: what we want, moving titles *outward*
p2 <- ggplot(mpg, aes(cty, hwy)) +
geom_point() +
theme_gray() +
theme(
axis.title.y = element_text(vjust = +3),
axis.title.x = element_text(vjust = -0.75)
)
# show plots side-by-side with patchwork package
p1 + p2 +
plot_annotation(tag_levels = "A")
For some reason the margin argument suggested by Didzis Elferts did not work for me. So, I used a different hack that is more flexible than adding an empty line but needs giving up the axis ticks.
myplot + theme(axis.ticks.x = element_blank(), axis.ticks.length.x = unit(3.25, "cm")
I guess, one can add the tick marks manually with geom_segment. Another possibility might be [ggalt::annotation_ticks][1]but I didn't bother trying either (note the current version of ggalt on CRAN (0.4) does not support this function, the one on github (0.6) does).

Resources