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)
Related
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
I am creating several plots in order to create frames for a gif. It is supposed to show growing points over time. (see plot 1 and 2 - the values increase). Using size aesthetic is problematic, because the scaling is done for each plot individually.
I tried to set breaks with scale_size_area() to provide a sequence of absolute values, in order to scale on 'all values' rather than only the values present in each plot. (no success).
Plot 3 shows how the points should be scaled, but this scaling should be achieved in each plot.
library(tidyverse)
df1 <- data.frame(x = letters[1:5], y = 1:5, size2 = 21:25)
ggplot(df1, aes(x, y, size = y)) +
geom_point() +
scale_size_area(breaks = seq(0,25,1))
ggplot(df1, aes(x, y, size = size2)) +
geom_point() +
scale_size_area(breaks = seq(0,25,1))
df2 <- data.frame(x = letters[1:5], y = 1:5, size2 = 21:25) %>% gather(key, value, y:size2)
ggplot(df2, aes(x, value, size = value)) +
geom_point() +
scale_size_area(breaks = seq(0,25,1))
Created on 2019-05-12 by the reprex package (v0.2.1)
Pass lower and upper bound to limits argument in scale_size_area function:
ggplot(df1, aes(x, y, size = y)) +
geom_point() +
labs(
title = "Y on y-axis",
size = NULL
) +
scale_size_area(limits = c(0, 25))
ggplot(df1, aes(x, y, size = size2 )) +
geom_point() +
labs(
title = "size2 on y-axis",
size = NULL
) +
scale_size_area(limits = c(0, 25))
How about this?
library("ggplot2")
df1 <- data.frame(x = letters[1:5],
y = 1:5)
ggplot(data = df1,
aes(x = x,
y = y,
size = y)) +
geom_point() +
scale_size_area(breaks = seq(1,25,1),
limits = c(1, 25))
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"))
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)))
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))