I have below ggplot (from https://wilkelab.org/ggtext/reference/geom_richtext.html)
library(ggplot2)
df <- data.frame(
label = c(
"Some text **in bold.**",
"Linebreaks<br>Linebreaks<br>Linebreaks",
"*x*<sup>2</sup> + 5*x* + *C*<sub>*i*</sub>",
"Some <span style='color:blue'>blue text **in bold.**</span><br>And *italics text.*<br>
And some <span style='font-size:18pt; color:black'>large</span> text."
),
x = c(.2, .1, .5, .9),
y = c(.8, .4, .1, .5),
hjust = c(0.5, 0, 0, 1),
vjust = c(0.5, 1, 0, 0.5),
angle = c(0, 0, 45, -45),
color = c("black", "blue", "black", "red"),
fill = c("cornsilk", "white", "lightblue1", "white")
)
ggplot(df) +
aes(
x, y, label = label, angle = angle, color = color, fill = fill,
hjust = hjust, vjust = vjust
) +
geom_richtext() +
geom_point(color = "black", size = 2) +
scale_color_identity() +
scale_fill_identity() +
xlim(0, 1) + ylim(0, 1)
I would like to add some transparency to the label background. When I apply alpha = 0.30, both text and background are affected. I there any way to adjust alpha of background?
#stefan suggested to use scales::alpha, however this is not working in below case
library(ggplot2)
library(ggtext)
ggplot(data.frame(x = c(-2, 2)), aes(x = x)) +
stat_function(fun = dnorm) +
geom_richtext(data = data.frame(x = c(-1.4, -.5), y = rep(dnorm(0, 2)), y1 = c('First', 'Second')),
aes(x = x, y = y, label = y1, fill = alpha(y1, 0.2))) +
scale_fill_manual(breaks = c('First', 'Second'), values = c('#c1121f', '#023e8a'), aesthetics = 'fill')
With this I am getting below error
Error: Unknown colour name: First
One option would be to use scales::alpha to set the alpha for the fill color:
library(ggplot2)
library(ggtext)
ggplot(df) +
aes(
x, y, label = label, angle = angle, color = color, fill = fill,
hjust = hjust, vjust = vjust
) +
geom_richtext(aes(fill = alpha(fill, 0.30))) +
geom_point(color = "black", size = 2) +
scale_color_identity() +
scale_fill_identity() +
xlim(0, 1) + ylim(0, 1)
EDIT For your second example we could or have to apply scales::alpha on the values of the fill scale. This however works only if we use the fill aes only in geom_richtext. If this is not the case than of course could we still apply one of both approaches side-by-side with the ggnewscale package.
library(ggplot2)
library(ggtext)
ggplot(data.frame(x = c(-2, 2)), aes(x = x)) +
stat_function(fun = dnorm) +
geom_richtext(
data = data.frame(x = c(-1.4, -.5), y = rep(dnorm(0, 2)), y1 = c("First", "Second")),
aes(x = x, y = y, label = y1, fill = y1)
) +
scale_fill_manual(
breaks = c("First", "Second"),
values = alpha(c("#c1121f", "#023e8a"), .2),
aesthetics = "fill"
)
Here is an alternative approach:
According to the documentation of ggtext
library(ggplot2)
library(ggtext)
ggplot(df) +
aes(
x, y, label = label, angle = angle, color = color,
hjust = hjust, vjust = vjust
) +
geom_richtext(
fill = NA, label.color = df$color, # remove background and outline
label.padding = grid::unit(rep(5, 10), "pt") # remove padding
) +
geom_point(color = "black", size = 2) +
scale_color_identity() +
xlim(0, 1) + ylim(0, 1)
Related
I was wondering if it is possible to have a geom_rect with a color gradient without a data reference, i.e. outside of aes().
I would like the two rectangles in the bottom of the following plot to show a color gradient from red to white (left to right) and the top one to show a color gradient from yellow to white.
Is this possible in a simple way or do I have to create data to refer to?
ggplot() +
geom_rect(aes(xmin = c(1, 3), xmax = c(2.5, 4), ymin = c(1, 1), ymax = c(2, 2)), color = "black", fill = "red") +
geom_rect(aes(xmin = 1, xmax = 3.5, ymin = 3, ymax = 4), color = "black", fill = "yellow") +
theme_bw() +
theme(panel.grid = element_blank())
I tried to use scale_fill_gradient with geom_tile but this doesn't really do what I want: 1. the two supposed-to-be-red rectangles share a gradient and don't start with pure red each and 2. I can't manage to use two different scale_fill_gradient's in one plot.
foo <- tibble(x = seq(from = 1, to = 2.5, by = 0.001),
y = rep(1, 1501))
bar <- tibble(x = seq(from = 3, to = 4, by = 0.001),
y = rep(1, 1001))
foobar <- tibble(x = seq(from = 1, to = 3.5, by = 0.001),
y = rep(3, 2501))
ggplot() +
geom_tile(data = foo, aes(x = x, y = y, fill = x)) +
geom_tile(data = bar, aes(x = x, y = y, fill = x)) +
scale_fill_gradient(low = 'red', high = 'white') +
geom_tile(data = foobar, aes(x = x, y = y, fill = x)) +
scale_fill_gradient(low = 'yellow', high = 'white') +
theme_bw() +
theme(panel.grid = element_blank())
You could use the function new_scale_fill from ggnewscale between your two different scale_fill_gradient functions in your plot process. This will reset your aesthetics to make it possible to use another gradient like this:
library(tibble)
foo <- tibble(x = seq(from = 1, to = 2.5, by = 0.001),
y = rep(1, 1501))
bar <- tibble(x = seq(from = 3, to = 4, by = 0.001),
y = rep(1, 1001))
foobar <- tibble(x = seq(from = 1, to = 3.5, by = 0.001),
y = rep(3, 2501))
library(ggplot2)
library(ggnewscale)
ggplot() +
geom_tile(data = foo, aes(x = x, y = y, fill = x)) +
geom_tile(data = bar, aes(x = x, y = y, fill = x)) +
scale_fill_gradient(low = 'red', high = 'white') +
new_scale_fill() +
geom_tile(data = foobar, aes(x = x, y = y, fill = x)) +
scale_fill_gradient(low = 'yellow', high = 'white') +
theme_bw() +
theme(panel.grid = element_blank())
Created on 2022-09-23 with reprex v2.0.2
To add for each geom_tile a gradient color, you could use for each tile new_scale_fill like this:
library(ggplot2)
library(ggnewscale)
ggplot() +
geom_tile(data = foo, aes(x = x, y = y, fill = x)) +
scale_fill_gradient(low = 'red', high = 'white', guide = 'none') +
new_scale_fill() +
geom_tile(data = bar, aes(x = x, y = y, fill = x)) +
scale_fill_gradient(low = 'red', high = 'white') +
new_scale_fill() +
geom_tile(data = foobar, aes(x = x, y = y, fill = x)) +
scale_fill_gradient(low = 'yellow', high = 'white') +
theme_bw() +
theme(panel.grid = element_blank())
Created on 2022-09-23 with reprex v2.0.2
I created the following plot using ggplot:
y1 <- runif(20,-2,7)
y2 <- c(-0.30306664,0.14744265 , 0.43857131 ,-0.04536794 ,-1.41432016,0.51887010 , 6.34925495 , 2.82511601 , 2.84251791, 4.05300569,-2.34208042, -0.29278747 , 0.49661933 , 0.75099908 ,1.12097713,2.72244949 , 2.23933230 , 1.86667714 , 2.17540024 , 7.56568823)
x <- 2001:2020
ggplot() +
geom_rect(aes(xmin=2006.90, xmax=2009.15,ymin=-Inf,ymax=10, fill='blue'), alpha= 0.4)+geom_rect(aes(xmin=2019.80, xmax=Inf,ymin=-Inf,ymax=10, fill='orange'), alpha= 0.3)+geom_rect(aes(xmin=2009.90, xmax=2013.15,ymin=-Inf,ymax=10, fill="lightgreen"), alpha= 0.4)+
geom_line(aes(x=x,y = y1),colour="black")+geom_line(aes(x=x,y = y2),colour="red")+
geom_point(aes(x=x,y = y1),col="black")+
geom_point(aes(x=x,y = y2),col="red")+
theme_classic()+
scale_fill_manual(name="",values = c("lightblue","lightgreen","orange"),labels=c(" R","k","C"))+theme(legend.position = "bottom")+ theme(axis.text.x = element_text(angle = 90))+geom_hline(yintercept = 0, color="black", size=1)
I have one legend to explain the content of the rectangles of the graph, but I need to add another legend to explain the two lines which are black and red. I wondered how to add another legend with a different position than the one that already exists to explain the names of the lines?
Can anyone help?
Move color inside aes, add scale_color_identity to get the right colors and to set the labels for the legend:
library(ggplot2)
ggplot() +
geom_rect(aes(xmin = 2006.90, xmax = 2009.15, ymin = -Inf, ymax = 10, fill = "blue"), alpha = 0.4) +
geom_rect(aes(xmin = 2019.80, xmax = Inf, ymin = -Inf, ymax = 10, fill = "orange"), alpha = 0.3) +
geom_rect(aes(xmin = 2009.90, xmax = 2013.15, ymin = -Inf, ymax = 10, fill = "lightgreen"), alpha = 0.4) +
geom_line(aes(x = x, y = y1, colour = "black")) +
geom_line(aes(x = x, y = y2, colour = "red")) +
geom_point(aes(x = x, y = y1, col = "black")) +
geom_point(aes(x = x, y = y2, col = "red")) +
scale_color_identity(name = NULL, labels = c(black = "Label 1", red = "Label 2"), guide = "legend") +
theme_classic() +
scale_fill_manual(name = "", values = c("lightblue", "lightgreen", "orange"), labels = c(" Rezession", "krise", "Corona 2020-")) +
theme(legend.position = "bottom") +
theme(axis.text.x = element_text(angle = 90)) +
geom_hline(yintercept = 0, color = "black", size = 1)
I'm looking for a way to move every second x-axis tick downwards and have the tick line go down with it.
I can change the general margin and tick length for all ticks with:
#MWE
library(ggplot2)
ggplot(cars, aes(dist, speed))+
geom_point()+
theme(
axis.ticks.length.x = unit(15, "pt")
)
But, I would like the x-axis ticks 0, 50, and 100 (i.e., every second tick) to be without the added top margin.
A generalized answer is preferred as my x-axis is categorical and not numerical (and contains 430 ticks, so nothing I can set by hand).
Any ideas?
Edit:
Output should be:
Edit2:
A more intricate example would be:
#MWE
ggplot(diamonds, aes(cut, price, fill = clarity, group = clarity))+
geom_col(position = 'dodge')+
theme(
axis.ticks.length.x = unit(15, "pt")
)
Edit -- added categorical approach at bottom.
Here's a hack. Hope there's a better way!
ticks <- data.frame(
x = 25*0:5,
y = rep(c(-0.2, -2), 3)
)
ggplot(cars, aes(dist, speed))+
geom_point()+
geom_rect(fill = "white", xmin = -Inf, xmax = Inf,
ymin = 0, ymax = -5) +
geom_segment(data = ticks,
aes(x = x, xend = x,
y = 0, yend = y)) +
geom_text(data = ticks,
aes(x = x, y = y, label = x), vjust = 1.5) +
theme(axis.ticks.x = element_blank()) +
scale_x_continuous(breaks = 25*0:5, labels = NULL, name = "") +
coord_cartesian(clip = "off")
Here's a similar approach used with a categorical x.
cats <- sort(as.character(unique(diamonds$cut)))
ticks <- data.frame(x = cats)
ticks$y = ifelse(seq_along(cats) %% 2, -500, -2000)
ggplot(diamonds, aes(cut, price, fill = clarity, group = clarity))+
geom_col(position = 'dodge') +
annotate("rect", fill = "white",
xmin = 0.4, xmax = length(cats) + 0.6,
ymin = 0, ymax = -3000) +
geom_segment(data = ticks, inherit.aes = F,
aes(x = x, xend = x,
y = 0, yend = y)) +
geom_text(data = ticks, inherit.aes = F,
aes(x = x, y = y, label = x), vjust = 1.5) +
scale_x_discrete(labels = NULL, name = "cut") +
scale_y_continuous(expand = expand_scale(mult = c(0, 0.05))) +
theme(axis.ticks.x = element_blank()) +
coord_cartesian(clip = "off")
Consider this simple example
library(tidyverse)
tibble(x = as.factor(c('good', 'neutral', 'bad')),
y = as.factor(c('bad', 'neutral', 'bad'))) %>%
ggplot(aes(x = x, y = y)) + geom_point()
I would like to put the x labels (good, neutral, bad) in different colored boxes. For instance, good (on both the x and y axis) would be surrounded on a small green box, and so on.
Can I do that in ggplot2?
Like this?
tibble(x = as.factor(c('good', 'neutral', 'bad')),
y = as.factor(c('bad', 'neutral', 'bad'))) %>%
ggplot(aes(x = x, y = y)) +
geom_point() +
theme(axis.text.x = element_text(color = c('red', 'blue', 'green')))
Your Plot:
EDIT
An alternate pretty Ghetto solution using grid
tibble(x = as.factor(c('good', 'neutral', 'bad')),
y = as.factor(c('bad', 'neutral', 'bad'))) %>%
ggplot(aes(x = x, y = y)) +
geom_point()
grid::grid.polygon(x = c(.3,.3,.25,.25), y = c(.07,.04,.04,.07),gp = gpar(col = 'green', fill = 'green', alpha = .5))
grid::grid.polygon(x = c(.525,.525,.575,.575), y = c(.07,.04,.04,.07),gp = gpar(col = 'red', fill = 'red', alpha = .5))
grid::grid.polygon(x = c(.79,.79,.86,.86), y = c(.07,.04,.04,.07),gp = gpar(col = 'blue', fill = 'blue', alpha = .5))
Solution using geom_label outside the plot area:
ggplot(data, aes(x, y)) +
geom_point() +
geom_label(aes(0.3, y, label = y, fill = y), hjust = 0) +
geom_label(aes(x, 0.45, label = x, fill = x)) +
theme_minimal() +
theme(
axis.text = element_blank(),
axis.ticks = element_blank(),
legend.position = "none"
) +
coord_cartesian(xlim = c(1, 3), ylim = c(1, 2), clip = "off")
Another solution
You should create geom_rect with borders, but without fill and plot them outside the plot area (using coord_cartesian):
library(tidyverse)
data <- tibble(
x = as.factor(c('good', 'neutral', 'bad')),
y = as.factor(c('bad', 'neutral', 'bad'))
)
ggplot(data, aes(x, y)) +
geom_point() +
# put rects on y-axis
geom_rect(aes(xmin = 0.1, xmax = 0.45, color = y,
ymin = as.numeric(y) - 0.1, ymax = as.numeric(y) + 0.1),
fill = NA, size = 3) +
# put rects on x-axis
geom_rect(aes(ymin = 0.3, ymax = 0.4, color = x,
xmin = as.numeric(x) - 0.15, xmax = as.numeric(x) + 0.15),
fill = NA, size = 3) +
# Here it's important to specify that your axis goes from 1 to max number of levels
coord_cartesian(xlim = c(1, 3), ylim = c(1, 2), clip = "off")
Another approach
Create a vector of colors and pass them into axis.text.x() option of theme().
# data
x = as.factor(c('good', 'neutral', 'bad'))
y = as.factor(c('bad', 'neutral', 'bad'))
df<- data.frame(x,y)
# create a vector of colors
mycolors<- c("red","blue","green")
library(ggplot2)
ggplot(df, aes(x = x, y=y))+
geom_point()+
theme(axis.text.x = element_text(colour = mycolors))
One approach could be this:
tibble(x = as.factor(c('good', 'neutral', 'bad')),
y = as.factor(c('bad', 'neutral', 'bad'))) %>%
ggplot(aes(x = x, y = y)) + geom_point()+
geom_rect(aes(xmin=0.5, xmax=1.5, ymin=-Inf, ymax=Inf), fill="red", alpha=0.1)+
geom_rect(aes(xmin=1.5, xmax=2.5, ymin=-Inf, ymax=Inf), fill="yellow", alpha=0.1)+
geom_rect(aes(xmin=2.5, xmax=3.5, ymin=-Inf, ymax=Inf), fill="green", alpha=0.1)
With geom_rect() you can add colored backgrounds:
I have a bubble chart and I'm using ggrepel to avoid overlapping labels.
Reproducible example:
library(randomcoloR)
n <- nrow(iris)
palette <- unname(distinctColorPalette(n))
(p <- iris %>%
ggplot(aes(x=Sepal.Length,
y=Sepal.Width,
label = Species,
color = palette)) +
geom_point(alpha = 0.7, show.legend = FALSE) +
scale_color_manual(values=palette)
)
(r <-
p + geom_point(
aes(size = Petal.Length*Petal.Width),
pch = 21,
show.legend = FALSE,
fill = palette
) +
scale_size_continuous(range = c(2, 30)) +
geom_text_repel(segment.color = "orange",
nudge_y = 0.05,
angle = 0,
vjust = -5,
segment.size = 0.2) +
theme(legend.position = "none")
)
The issue is I want the label the same color the bubble but I'm getting the color of the circle border instead.
Your color and fill should be inside aesthetics aes(), then ggrepel will recognise them. I mean ggrepel use that one which specified in aes
I've rewrite your code a bit:
library(randomcoloR)
library(ggrepel)
n <- nrow(iris)
palette <- unname(distinctColorPalette(n))
iris %>%
ggplot(aes(x=Sepal.Length,
y=Sepal.Width)) +
geom_point(
aes(size = Petal.Length*Petal.Width,
fill = palette,
color = palette),
alpha = .7,
pch = 21,
show.legend = FALSE) +
scale_size_continuous(range = c(2, 30)) +
geom_text_repel(aes(label = Species,
color = palette),
segment.color = "orange",
nudge_y = 0.05,
angle = 0,
vjust = -5,
segment.size = 0.2) +
theme(legend.position = "none")