I'm plotting a time series value with its percentages using facet_wrap
in ggplot:
For the plot below, the upper plot is the value, and the lower plot is percentage change. And I would like the y-axis in the lower plot to be "%". Normally in ggplot I would do something like
+ scale_y_continuous(labels = scales::percent)
But since I'm using facet_wrap, how do I specify that I only want one of the 2 plots' y-axis label to be percentages?
P.S. Here is the code to generate this plot:
library(data.table)
library(ggplot2)
library(scales)
library(dplyr)
pct <- function(x) {x/lag(x)-1}
Dates = seq(from = as.Date("2000-01-01"),
to =as.Date("2018-10-01"),
by = "1 month")
set.seed(1024)
this_raw = data.frame(CM = Dates,
value = rnorm(n = length(Dates)),
variable = rep("FAKE",length(Dates)))
this_diff = na.omit(as.data.table(this_raw %>%
group_by(variable) %>%
mutate_each(funs(pct), c(value))))
this_diff$type = "PerCng"
this_raw$type = "RAW"
plot_all = rbindlist(list(this_raw,this_diff))
plot_all$type = factor(plot_all$type, levels = c("RAW", "PerCng"))
out_gg = plot_all %>%
ggplot(aes(x=CM, y=value)) +
geom_line(color = "royalblue3") +
theme(legend.position='bottom')+
ggtitle("FAKE DATA") +
facet_wrap(~ type, scale = "free_y", nrow = 2,
strip.position = "left",
labeller = as_labeller(c(RAW = "Original", PerCng = "% Change") ) )+
scale_x_date(date_breaks = "12 month", date_labels = "%Y-%m",
date_minor_breaks = "3 month")+
ylab("")+
theme(plot.title = element_text(hjust = 0.5,size = 12),
axis.text.x = element_text(size = 6,angle = 45, hjust = 1),
axis.text.y = element_text(size = 6),
axis.title.y = element_text(size = 6)) +
theme(strip.background = element_blank(),
strip.placement = "outside")+
theme(legend.title=element_blank())
print(out_gg)
Since we need to add percentages in the labels of the Y-axis, the keyword “labels” is used. Now use scales: : percent to convert the y-axis labels into a percentage. This will scale the y-axis data from decimal to percentage. It simply multiplies the value by 100.
To alter the labels on the axis, add the code +labs(y= "y axis name", x = "x axis name") to your line of basic ggplot code. Note: You can also use +labs(title = "Title") which is equivalent to ggtitle .
The scale_x_continuous() and scale_y_continuous() methods can be used to disable scientific notation and convert scientific labels to discrete form.
The easiest way to change the Y-axis title in base R plot is by using the ylab argument where we can simply type in the title. But the use of ylab does not help us to make changes in the axis title hence it is better to use mtext function, using which we can change the font size, position etc. of the title.
I agree with the above comments that facets are really not intended for this use case. Aligning separate plots is the orthodox way to go.
That said, if you already have a bunch of nicely formatted ggplot objects, and really don't want to refactor the code just for axis labels, you can convert them to grob objects and dig underneath the hood:
library(grid)
# Convert from ggplot object to grob object
gp <- ggplotGrob(out_gg)
# Optional: Plot out the grob version to verify that nothing has changed (yet)
grid.draw(gp)
# Also optional: Examine the underlying grob structure to figure out which grob name
# corresponds to the appropriate y-axis label. In this case, it's "axis-l-2-1": axis
# to the left of plot panels, 2nd row / 1st column of the facet matrix.
gp[["layout"]]
gtable::gtable_show_layout(gp)
# Some of gp's grobs only generate their contents at drawing time.
# Using grid.force replaces such grobs with their drawing time content (if you check
# your global environment, the size of gp should increase significantly after running
# the grid.force line).
# This step is necesary in order to use gPath() to generate the path to nested grobs
# (& the text grob for y-axis labels is nested rather deeply inside the rabbit hole).
gp <- grid.force(gp)
path.to.label <- gPath("axis-l-2", "axis", "axis", "GRID.text")
# Get original label
old.label <- getGrob(gTree = gp,
gPath = path.to.label,
grep = TRUE)[["label"]]
# Edit label values
new.label <- percent(as.numeric(old.label))
# Overwrite ggplot grob, replacing old label with new
gp = editGrob(grob = gp,
gPath = path.to.label,
label = new.label,
grep = TRUE)
# plot
grid.draw(gp)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With