I have a bar plot in R using
ggplot2::geom_bar(data = data,
mapping = ggplot2::aes(
x = values_for_x,
y = values_for_y,
color = factor_levels_for_color,
fill = factor_levels_for_color,
alpha = factor_levels_for_alpha
),
position = ggplot2::position_dodge2(
preserve = "total"
),
stat = "identity",
linewidth = 0
)
As you can see, I have 3 different columns defining color
, fill
and alpha
.
Currently, my dodged bars are first ordered/grouped by alpha
and the by color
. However, I would like to have them first ordered by the color
and then by alpha
.
I am currently stuck finding the right position to define this. Any help/hint is appreciated!
Thanks!
The following code plots a ggplot. It does order all dodged bars first by the levels of the alpha
value, then using the color_values
factor levels.
I would like to switch this, but fail so far to do this.
While this is a minimal example, my code defines the levels manually and also assigns specific color or alpha values to certain values that I do not want to change.
Thanks again!
data <- base::data.frame(
x_values = rep(x = c("Treatment 1", "Treatment 2", "Treatment 3"), times = 3),
y_values = c(5,8,7,3,7,8,3,1,5),
alpha_values = c(1,2,3,1,2,3,1,2,3),
group = "A",
color_values = c("location1", "location1", "location1",
"location2", "location2", "location2",
"location3", "location3", "location3")
)
data2 <- base::data.frame(
x_values = rep(x = c("Treatment 1", "Treatment 2", "Treatment 3"), times = 3),
y_values = c(17,18,17,13,17,18,13,11,15),
alpha_values = c(7,7,7,3,3,3,5,5,5),
group = "B",
color_values = c("location3", "location3", "location3",
"location1", "location1", "location1",
"location2", "location2", "location2")
)
data <- dplyr::bind_rows(base::list(data, data2))
data$alpha_values <- base::as.factor(data$alpha_values)
data$group <- base::as.factor(data$group)
data$color_values <- base::as.factor(data$color_values)
ggplot2::ggplot(data = data,
mapping = ggplot2::aes(x = x_values,
y = y_values,
alpha = alpha_values,
fill = color_values)) +
ggplot2::geom_bar(stat = "identity", position = ggplot2::position_dodge2())
One approach could be to make a factor that combines the color and alpha values, and order it the way you want. For instance you can order it using multiple variables using dplyr::arrange
, and then make a new factor variable that respects that compound order using forcats::fct_inorder
:
ggplot2::ggplot(data = data |>
dplyr::arrange(color_values, alpha_values) |>
dplyr::mutate(order = forcats::fct_inorder(paste(color_values, alpha_values))),
mapping = ggplot2::aes(x = x_values,
y = y_values,
alpha = alpha_values,
fill = color_values,
group = order)) +
ggplot2::geom_bar(stat = "identity", position = ggplot2::position_dodge2())
In very limited circumstances you could skip the "new combined factor" step and use group = interaction(alpha_values, color_values)
in your aes()
to get the same result -- provided your factors are alphanumerically ordered like in your example case. ?interaction
says the result is unordered, but in your example the factors are alphanumerically ordered, so interaction(data$alpha_values, data$color_values)
outputs [1] 1.location1 2.location1 3.location1 1.location2 ...
), which happens to have the order you want. This won't work in most cases, though, e.g. if the numbers exceed 9, or if the factors don't happen to be alphabetically ordered.
In some circumstances, it might suffice to add group = color_values
to tell ggplot2 that the dodging should be done (primarily) based on color_values
, and not by alpha_values
. Dodging behaviour is specified by the group
aesthetic, and it appears that when it is not specified, but color
and alpha
are, the default is to group by the alpha
mapping.