ggplot2 facet labeller double subscript - r

I'm plotting variables with double subscripts, and I would like to be able to keep the subscripts from getting mashed together in the facet strip text. Each label should display something like $\beta_{1, 12}$ instead of $\beta_112$. It should be enough to fix the following MWE.
d = data.frame(
x = rnorm(6),
y = rnorm(6),
z = rep(paste0("beta[", 1:3, "][", 12, "]"), each = 2))
library(ggplot2)
pl = ggplot(d) +
geom_point(aes(x, y)) +
facet_wrap(~z, labeller = label_parsed)

How about this?
library(ggplot2)
d = data.frame(
x = rnorm(6),
y = rnorm(6),
z = rep(paste0("beta[", 1:3, "~~", 12, "]"), each = 2))
pl = ggplot(d) +
geom_point(aes(x, y)) +
facet_wrap(~z, labeller = label_parsed)
pl

Related

paste function for labeling in ggplot2

In the following plot, I want to rename x-axis by paste0 function.
daata <- data.frame(
q = paste0("q",1:20),
value = runif(n = 20, 2, 10))
ggplot2::ggplot(data = daata, aes(x = q, y = value)) +
geom_col()
so I used the following code:
q = paste0("q",1:20)
labels <- paste0("'", q,"'" , " = ", 1:20) %>% noquote()
# Or
labels <- noquote(paste0("'", q,"'" , " = ", 1:20))
ggplot2::ggplot(data = daata, aes(x = q, y = value)) +
geom_col() +
scale_x_discrete(labels = labels)
But it did not work. Why? (main question)
I want to search for solutions that make labels = c("'q1' = 1", ...) works.
Beside paste function I know two alternatives.
Using list:
labels = sapply(1:20, list)
names(labels) <- daata$q
ggplot2::ggplot(data = daata, aes(x = q, y = value)) +
geom_col() +
scale_x_discrete(labels = labels)
Using function:
ggplot2::ggplot(data = daata, aes(x = q, y = value)) +
geom_col() +
scale_x_discrete(labels = function(i){gsub("q", "", i)})
I am eager to know other solutions too.
How about something like this? Extract the question number in the data = step, and use that for the axis:
daata <- data.frame(
q = paste0("q",1:20),
value = 1:20)
ggplot2::ggplot(data = daata %>% mutate(order = str_remove(q, "q") %>% as.numeric),
aes(x = order, y = value)) +
geom_col() +
scale_x_continuous(breaks = 1:20, minor_breaks = NULL)
Edit: here's an alternative that extracts the numeric part of the label. As you'll note, this preserves the alphabetical ordering created by mapping x to q.
ggplot2::ggplot(data = daata, aes(x = q, y = value)) +
geom_col() +
scale_x_discrete(labels = function(x) parse_number(x))
why not giving a named vector?
labels <- parse_number(as.character(daata$q))
names(labels) <- as.character(daata$q)
p1 <- ggplot2::ggplot(data = daata, aes(x = q, y = value)) +
geom_col()
p2 <- p1 + scale_x_discrete(labels = labels)
cowplot::plot_grid(p1, p2, nrow = 1)

Two different color keys in ggplot

I would like to plot points twice using two diferent color scales:
In the exemple here 5 points are drown and color is mapped to two covariates (cov1 and cov2): cov1 and cov2 are in different scales 1 to 5 and 0.01 to 0.05 respectively.
I wish to have 2 independent color keys, one for cov1 and one for cov2,
a bit like in the graph below. However on the graph below I used 'color = cov1' end 'fill = cov2' in order to bring another color key...
Any help would be appreciated.
gg1 <- ggplot(data = df1 , aes( x = x , y = y ) ) +
geom_point( aes(x = x , y = y - 1 , color = cov1 )) +
geom_point( aes(x = x , y = y + 1 , color = cov2 )) +
scale_y_continuous(limits = c(-3,3))
gg2 <- ggplot(data = df1 , aes( x = x , y = y ) ) +
geom_point( aes(x = x , y = y - 1 , color = cov1 )) +
geom_point( aes(x = x , y = y + 1 , fill = cov2 ), pch = 21 ) +
scale_y_continuous(limits = c(-3,3))
grid.arrange( gg1 , gg2 , ncol = 2 )
In basic ggplot2 it is impossible if I remember correctly. But this repository may be your answer:
https://github.com/eliocamp/ggnewscale
or this (mentioned in description of the previous one):
https://github.com/clauswilke/relayer
I haven't been using ggplot2 for quite a long time so I'm not familiar with these two, but I remember that I used one of them at least once.
I've just wrote quick example to check if it works:
d1 <- data.frame(x=1:5, y=1)
d2 <- data.frame(x=1:5, y=2)
library(ggplot2)
library(ggnewscale)
ggplot() +
geom_point(data = d1, aes(x=x, y=y, color = x)) +
scale_color_continuous(low = "#0000aa", high="#ffffff") +
new_scale_color() +
geom_point(data = d2, aes(x=x, y=y, color = x)) +
scale_color_continuous(low = "#aa0000", high="#00aa00")
And it seems to work as you want.
I used your idea about combining col and fill and small hack to use different shapes for cov1 and cov2:
# sample data
my_data <- data.frame(x = 1:5,
cov1 = 1:5,
cov2 = seq(0.01, 0.05, 0.01))
library(ggplot2)
ggplot() +
geom_point(data = my_data, aes(x = x, y = 0.5, col = cov1), shape = 16) +
scale_color_continuous(low = "red1", high = "red4") +
geom_point(data = my_data, aes(x = x, y = -0.5, fill = cov2), shape = 21, col = "white", size = 2) +
ylim(-1, 1)
Hope it helps.

With ggplot, use both unit_format and dollar_format from scales for tick text labeling

I have created the following ggplot to highlight my issue:
mydf = data.frame(x = c(1,2,3,4,5), y = c(1,2,3,4,5))
ggplot(data = mydf) +
geom_point(aes(x = x, y = y)) +
scale_x_continuous(labels = scales::dollar_format()) +
scale_y_continuous(labels = scales::unit_format(unit = "M"))
which gives the following amazing, advanced ggplot graph:
My question is then simply - how can i make one axis have both the $ and M unit labels, so that the label shows as $1M $2M, etc. Is this possible? Is it also possible to reduce the gap between the number and the M sign, so that it shows 5M instead of 5 M
Thanks as always!
Hacky, but works:
ggplot(data = mydf) +
geom_point(aes(x = x, y = y)) +
scale_x_continuous(labels = scales::dollar_format()) +
scale_y_continuous(labels = scales::dollar_format(prefix="$", suffix = "M"))
You can also define your own function:
ggplot(data = mydf) +
geom_point(aes(x = x, y = y)) +
scale_x_continuous(labels = f <- function(x) paste0("$",x,"M")) +
scale_y_continuous(labels = f)
A method using y with unit_format() function to generate desired result - tick label y as "$1M", no gap between dollar and amount, no gap between amount and M:
mydf = data.frame(x = c(1,2,3,4,5), y = c(1,2,3,4,5))
ggplot(data = mydf) +
geom_point(aes(x = x, y = y)) +
scale_x_continuous(labels = scales::dollar_format()) +
scale_y_continuous(labels = scales::unit_format(unit = "M", prefix = "$", sep = "", accuracy = 1))
Using Roman's method - since y is using dollar format, results are same without prefix = "$" argument in dollar_format() function:
ggplot(data = mydf) +
geom_point(aes(x = x, y = y)) +
scale_x_continuous(labels = scales::dollar_format()) +
scale_y_continuous(labels = scales::dollar_format(suffix = "M"))

scale_y_discrete ignores breaks/labels

Bug? Possibly related to this..
dat = data.frame(x = 1:4, y = ordered(c(4,'>5',1,1), levels = c(1:5, '>5')), grp = 1)
ggplot(dat, aes(x, y, group=grp)) + geom_step() +
scale_y_discrete(breaks = levels(dat$y), labels = levels(dat$y))
ggplot(dat, aes(x, y, group=grp)) + geom_step() +
scale_y_discrete(breaks = levels(dat$y), labels = levels(dat$y), drop = FALSE)

geom_blank drops NA

Using geom_blank I want to add some new factor levels, but I can't seem to do this and keep the NA level
library('ggplot2')
pl <- ggplot(data.frame(x = factor(c(1:2, NA)), y = 1), aes(x, y)) + geom_point()
pl
pl + geom_blank(data = data.frame(x = addNA(factor(c(0:3, NA))), y = 1))
I would like to have the x at 0,1,2,3,NA using geom_blank
As I hoped in the comments, a work-around could be re-ordering the layers if the plot is already made, and this should work for ggplots in general.
library('ggplot2')
pl <- ggplot(data.frame(x = factor(c(1:2, NA)), y = 1), aes(x, y)) +
geom_point() +
geom_blank(data = data.frame(x = addNA(factor(c(0:3, NA))), y = 1))
## not what I want
pl
## this is what I want
pl$layers <- rev(pl$layers)
pl
Unfortunately, when you have multiple layers with separate datasets, factor levels can get messed overridden. You can fix this by setting the limits on the discrete scale:
pl <- ggplot(data.frame(x = factor(c(1:2, NA)), y = 1), aes(x, y)) + geom_point()
pl +
geom_blank(data = data.frame(x = addNA(factor(c(0:3, NA))), y = 1)) +
scale_x_discrete(limits=addNA(factor(c(0:3, NA))))
For some reason, this messes up the expansion on the axis and the NA break is at the right edge.
[
This can be fixed by manually setting the expand parameter to your liking.
pl <- ggplot(data.frame(x = factor(c(1:2, NA)), y = 1), aes(x, y)) + geom_point()
pl +
geom_blank(data = data.frame(x = addNA(factor(c(0:3, NA))), y = 1)) +
scale_x_discrete(limits=addNA(factor(c(0:3, NA))), expand=c(0.25,0.25))

Resources