geom_blank drops NA - r

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))

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

Reduce space between y axis and cathegories in a ggplot

I have made the graph below with ggplot. I would like to reduce the distance between the y axis and the first category (a). Which function should I use? Thanks! :)
library(ggplot2)
library(reshape2)
data <- data.frame(a = rnorm(10), b = rnorm(10), c = rnorm(10), group = 1:10)
data <- melt(data, id = "group")
ggplot(data, aes(x = variable, y = value, group = group, color = as.factor(group))) + geom_point() + geom_line() + theme_minimal() + theme(axis.line = element_line(), panel.grid = element_blank())
Suppose we have the following plot:
library(ggplot2)
df <- data.frame(x = rep(LETTERS[1:3], 3),
y = rnorm(9),
z = rep(letters[1:3], each = 3))
ggplot(df, aes(x, y, colour = z, group = z)) +
geom_line() +
geom_point()
We can reduce the space between the extreme points and the panel edges by adjusting the expand argument in a scale function:
ggplot(df, aes(x, y, colour = z, group = z)) +
geom_line() +
geom_point() +
scale_x_discrete(expand = c(0,0.1))
Setting expand = c(0,0) completely removes the space. The first argument is a relative number, the second an absolute; so in the example above we set the expand to 0.1 x-axis units.

Force size aesthetic to scale to given breaks

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))

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.

ggplot2 facet labeller double subscript

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

Resources