I would need help in order to color the x axis of a ggplot2 figure.
Here is what I can manage to do so far :
head(data)
x y group Axis_color
1 A 25 F G1
2 A 88 G G1
3 A 88 H G1
4 A 22 I G1
5 A 18 J G1
6 B 54 F G3
color_list<- c("F"="orange", "G"="darkgreen", "H"="grey", "I"="pink", "J"="purple", "G1"="blue","G2"="red","G3"="green")
ggplot(data, aes(x = x, y = y, fill = group, label = y))
coord_flip()
geom_bar(stat = "identity")
Which gives:
But I would like to as the column "Axis_color" in order to add colors stored in the color_list
to the x axis and get:
As you can see I get two different legends axis as well.
Here are the data if it can helps :
structure(list(x = c("A", "A", "A", "A", "A", "B", "B", "B",
"B", "B", "C", "C", "C", "C", "C", "D", "D", "D", "D", "D", "E",
"E", "E", "E", "E"), y = c(25, 88, 88, 22, 18, 54, 25, 37, 68,
72, 36, 84, 17, 64, 48, 15, 17, 72, 61, 25, 66, 10, 18, 99, 63
), group = c("F", "G", "H", "I", "J", "F", "G", "H", "I", "J",
"F", "G", "H", "I", "J", "F", "G", "H", "I", "J", "F", "G", "H",
"I", "J"), Axis_color = c("G1", "G1", "G1", "G1", "G1", "G3",
"G3", "G3", "G3", "G3", "G1", "G1", "G1", "G1", "G1", "G2", "G2",
"G2", "G2", "G2", "G3", "G3", "G3", "G3", "G3")), row.names = c(NA,
-25L), class = "data.frame")
CodePudding user response:
The most convenient solution I could come up with that includes a legend would be to use geom_text()
to place fake axis labels. If the legend isn't needed I would've recommended ggtext.
By placing the text at x = -Inf
, you place it at the axis' minimum and you can further nudge the text to the outside with hjust
. You'd need to turn off clipping in the coordinates for this to work. Alternatively you can also set x = -10
or something, but you'd have to adjust the scale limits and tailor this value to every plot.
# data <- structure(...) # omitted for brevity
library(ggplot2)
color_list<- c("F"="orange", "G"="darkgreen", "H"="grey", "I"="pink", "J"="purple", "G1"="blue","G2"="red","G3"="green")
ggplot(data, aes(x = y, y = x, fill = group, label = x))
geom_col()
geom_text(data = ~ subset(.x, !duplicated(x)),
aes(x = -Inf, colour = Axis_color), hjust = 2)
scale_fill_manual(values = color_list[1:5])
scale_colour_manual(values = color_list[-c(1:5)])
coord_cartesian(clip = "off")
theme(axis.text.y = element_text(colour = NA))
Small sidenote: I replaced geom_bar(stat = "identity")
with geom_col()
as that seems cleaner, and swapped the x and y aesthetics, removing the need for coord_flip()
.
CodePudding user response:
Another option to achieve your desired result would be to make use of the ggtext
package which allows to color the axis labels via some HTML/CSS.
To get a second legend I make use of the ggnewscale package as in the approach by @teunbrand. However, to make this work we have to add a second geom
, too. To this end I added a helper geom_col
where I set y=0
.
library(ggplot2)
library(ggtext)
library(dplyr)
library(tibble)
color_list <- c("F"="orange", "G"="darkgreen", "H"="grey", "I"="pink", "J"="purple", "G1"="blue","G2"="red","G3"="green")
axis_color <- dplyr::distinct(data, x, Axis_color) %>%
tibble::deframe()
ggplot(data, aes(x = x, y = y, fill = group, label = y))
coord_flip()
geom_bar(stat = "identity")
scale_fill_manual(values = color_list, limits = force, guide = guide_legend(order= 1))
scale_x_discrete(labels = ~ glue::glue("<span style='color: {color_list[axis_color[.x]]}'>{.x}</span>"))
ggnewscale::new_scale_fill()
geom_col(aes(y = 0, fill = Axis_color))
scale_fill_manual(values = color_list[unique(data$Axis_color)], guide = guide_legend(order= 2))
theme(axis.text.y = ggtext::element_markdown())