I have a similar question to this post, but I'd like to know if it's possible to both 1. keep my y-axis values in the same order, lowest to highest -> aes(y = reorder(species, -sal, FUN = median), x = sal))
and 2. change the default order of the y-axis labels when the values are tied; this solution doesn't fix the problem: scale_y_discrete(limits=rev)
. Currently, if values are tied, y-axis labels go in reverse alphabetical order. This normally wouldn't be a problem, but I want the labels to match up to the corresponding sample size annotations. When values are tied, this mixes up the proper order of the labels. Sample sizes per y-axis label are vastly different in my real dataframe, I just didn't know how to change this in the example df.
"E" and "D" are no longer in alphabetical order and values are tied. When values are tied, order should be A, B, D, E, C (like the pivot table).
set.seed(123)
df <- data.frame(
species = LETTERS[seq(from = 1, to = 5)],
sal = round(rnorm(n = 5, mean = 27, sd = .01), 2),
num = sample(x = 1:20, size = 20, replace = F)
)
pivot_df <- df %>%
group_by(species) %>%
summarize(n = n(), median_sal = median(sal, na.rm = T)) %>%
arrange(median_sal)
ggplot(
data = subset(df, !is.na(sal)),
aes(y = reorder(species, -sal, FUN = median), x = sal)
) +
geom_boxplot(outlier.shape = 1, outlier.size = 1, orientation = "y") +
coord_cartesian(clip = "off") +
annotation_custom(grid::textGrob(pivot_df$n,
x = 1.035,
y = c(0.89, 0.70, 0.51, 0.32, 0.13),
gp = grid::gpar(cex = 0.6)
)) +
annotation_custom(grid::textGrob(expression(bold(underline("N"))),
x = 1.035,
y = 1.02,
gp = grid::gpar(cex = 0.7)
)) +
ylab("") + xlab("") +
theme(
axis.text.y = element_text(size = 7, face = "italic"),
axis.text.x = element_text(size = 7),
axis.title.x = element_text(size = 9, face = "bold"),
axis.line = element_line(colour = "black"),
panel.background = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_rect(colour = "black", fill = NA, size = 1),
panel.grid.major = element_line(colour = "#E0E0E0"),
plot.title = element_text(hjust = 0.5),
plot.margin = margin(21, 40, 20, 20))
One option would be to set the order of species
according to the order in your pivot_df
instead of using reorder
. To this end I first convert pivot_df$species
to a factor
using forcats::fct_inorder(species)
. Afterwards I convert df$species
to a factor using factor(species, levels = rev(levels(pivot_df$species))
:
library(dplyr)
library(ggplot2)
pivot_df <- df %>%
group_by(species) %>%
summarize(n = n(), median_sal = median(sal, na.rm = T)) %>%
arrange(median_sal) |>
mutate(species = forcats::fct_inorder(species))
ggplot(
data = subset(df, !is.na(sal)),
aes(y = factor(species, levels = rev(levels(pivot_df$species))), x = sal)
) +
geom_boxplot(outlier.shape = 1, outlier.size = 1, orientation = "y") +
coord_cartesian(clip = "off") +
annotation_custom(grid::textGrob(pivot_df$n,
x = 1.035,
y = c(0.89, 0.70, 0.51, 0.32, 0.13),
gp = grid::gpar(cex = 0.6)
)) +
annotation_custom(grid::textGrob(expression(bold(underline("N"))),
x = 1.035,
y = 1.02,
gp = grid::gpar(cex = 0.7)
)) +
ylab("") + xlab("") +
theme(
axis.text.y = element_text(size = 7, face = "italic"),
axis.text.x = element_text(size = 7),
axis.title.x = element_text(size = 9, face = "bold"),
axis.line = element_line(colour = "black"),
panel.background = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_rect(colour = "black", fill = NA, size = 1),
panel.grid.major = element_line(colour = "#E0E0E0"),
plot.title = element_text(hjust = 0.5),
plot.margin = margin(21, 40, 20, 20))