Create a vector with multiple expressions - r

In the following ggplot barchart. How can I generate a vector with multiple expressions automatically?
data <- data.frame(x = LETTERS[1:11], y = 10^(0:10))
z <- 0:10
y.labels <- sprintf(paste0("10^", z))
ggplot(data, aes(x, y)) +
geom_bar(stat = "identity") +
scale_y_log10(breaks = 10^(z), labels = y.labels)
I've tried with bquote(.(10^c(z))), but is not the desired result .
My only alternative is to do it manually, but it is not automatic:
y.labels <- expression("10"^0, "10"^1, "10"^2, "10"^3, "10"^4, "10"^5, "10"^6, "10"^7, "10"^8, "10"^9, "10"^10)

Try parse(text =, which will convert the character vector y.labels into the expected expression:
ggplot(data, aes(x, y)) +
geom_bar(stat = "identity") +
scale_y_log10(breaks = 10^(z), labels = parse(text = y.labels))

We can use bquote with expression
y.labels <- sapply(z, function(u) as.expression(bquote(10^.(u))))
ggplot(data, aes(x, y)) +
geom_bar(stat = "identity") +
scale_y_log10(breaks = 10^(z), labels =y.labels)

If you don't need to store both z and y.labels, you can use:
library(scales)
data <- data.frame(x = LETTERS[1:11], y = 10^(0:10))
ggplot(data, aes(x, y)) +
geom_bar(stat = "identity") +
scale_y_log10(breaks = trans_breaks(log10, function(x) 10^x, 10),
labels = trans_format(log10, math_format(10^.x)))

Related

log_2(x + 1) transformation in ggplot2

I'm trying to implement the log_2(x + 1) transformation in ggplot2 but am running into issues.
Here is an MWE
library(ggplot2)
x <- rexp(100)
y <- rexp(100)
df <- data.frame(x = x, y = y)
p <- ggplot(df, aes(x = x, y = y)) + geom_point(colour = "blue") +
scale_x_continuous(trans = "log2") +
scale_y_continuous(trans = "log2")
print(p)
However, I'm unsure how to best go about transforming the axes, as well as labelling the axes as log_2{x + 1) and log_2(y + 1).
You could use log2_trans from scales with a function to add 1 like this:
library(ggplot2)
library(scales)
x <- rexp(100)
y <- rexp(100)
df <- data.frame(x = x, y = y)
p <- ggplot(df, aes(x = x, y = y)) + geom_point(colour = "blue") +
scale_x_continuous(trans = log2_trans(),
breaks = trans_breaks("log2", function(x) x + 1),
labels = trans_format("log2", math_format(.x + 1))) +
scale_y_continuous(trans = log2_trans(),
breaks = trans_breaks("log2", function(x) x + 1),
labels = trans_format("log2", math_format(.x + 1)))
print(p)
Created on 2022-11-04 with reprex v2.0.2

Plotting multiple plots with geom_violing and lapply

I'm trying to use lapply to make multiple violin plots, stacked side by side.
The base code is:
ggplot(mpg, aes(x = class, y = cyl, fill = class)) +
geom_violin() + ggtitle("cyl") +
geom_jitter(shape=16,position=position_jitter(0.1)
So I'm trying to use lapply:
plots_list = lapply(
names(mpg[,3:5]),
function(n)
ggplot(mpg, aes(x = class, y = n, fill = class)) +
geom_violin() + geom_jitter(shape=16, position=position_jitter(0.1))
+ ggtitle(n)
)
plots_list[[1]]
But y = n gives no violin plot.
If I use:
plots_list = lapply(
mpg[,3:5],
function(n)
ggplot(mpg, aes(x = class, y = n, fill = class)) +
geom_violin() + geom_jitter(shape=16, position=position_jitter(0.1)) + ggtitle(n)
)
plots_list[[1]]
Then the plots titles are not correct.
Also, when using:
grid.arrange(plots_list[1:3], ncol = 2)
I get errors, but ploting with:
plots_list[1:3]
works like a charm
Your n is not a symbol, it's a string, so you need aes_string:
plots_list = lapply(
names(mpg[,3:5]),
function(n)
ggplot(mpg, aes_string(x = "class", y = n, fill = "class")) +
geom_violin() + geom_jitter(shape=16, position=position_jitter(0.1))
+ ggtitle(n)
)
plots_list[[1]]

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)

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)

Resources