I need to display the labels of the x-axis both above and below my ggplot, aligned with the corresponding data points. I have already created a ggplot with the necessary data and aesthetics, but I am struggling to duplicated the x-axis because it is a categorical variable.
Since with scale_x_discrete is not possible to duplicate an axis, I tried to use scale_x_continuous(), splitting the categorical variable with breaks and defining a character vector as labels. 'plot' is my ggplot with data and aesthetics. The variable 'birds$species_name' is a factor containing the names of bird species, ordered by increasing percentage values.
library(ggplot2)
library(data.table)
birds <- data.frame(species_name= c("eagle", "eagle", "robin", "vulture", "bee-eater"),
overall.percentage = c(12, 33, 19, 20, 15))
# reorder the species according to their lowest percentage value
x <- setDT(birds)[,.(.(sort(overall.percentage))), species_name]
birds[
setorder(setDT(transpose(x[[2]]))[,species_name := x[[1]]])[,order := .I],
on = "species_name", order := order]
plot<-
ggplot(birds, aes(x=reorder(species_name, order), overall.percentage)) +
geom_point(position = position_jitter(w = 0.25, h = 0))
plot + scale_x_continuous(breaks = 1:length(unique(birds$species_name)),
labels = as.character(unique(birds$species_name)),
sec.axis = dup_axis())
As suggested by a previous question online, I also tried this code.
plot + scale_x_continuous(breaks = 1:length(unique(birds$species_name)),
labels = as.character(unique(birds$species_name)),
sec_axis(~.,
breaks = 1:length(unique(birds$species_name)),
labels = as.character(unique(birds$species_name))))
I would have expected the code to successfully duplicate the x-axis in my plot, but always returns me the error "Discrete value supplied to continuous scale". May it be a problem connected to the ordering action?
Any suggestion would be highly appreciated, thanks in advance!
The idea is that you transform your discrete axis in to a numeric one, supply the labels yourself and then you cna easily duplicated the axis:
library(ggplot2)
ggplot(iris, aes(x = as.integer(Species), y = Sepal.Width, color = Species)) +
geom_point(position = position_jitter(height = 0)) +
scale_x_continuous("Species",
breaks = seq_len(nlevels(iris$Species)),
labels = levels(iris$Species),
sec.axis = dup_axis()
) +
theme(panel.grid.minor = element_blank())
Based on your data you could do the following:
library(data.table)
## first modify the data such that species_name is
## a. a factor
## b. has the factor levels not in alphabetical order but sorted
## according to overall.percentage
setDT(birds)
birds[, species_name := reorder(factor(species_name),
overall.percentage, min)]
## then do your plot but use the integer positions and add labels manually
ggplot(birds, aes(x = as.integer(species_name), y = overall.percentage)) +
geom_point(position = position_jitter(w = 0.25, h = 0)) +
scale_x_continuous(breaks = birds[, seq_len(nlevels(species_name))],
labels = birds[, levels(species_name)],
sec.axis = dup_axis()) +
theme(panel.grid.minor = element_blank())