Ordering of factor levels in ggplot is a common issue, and there are a number of posts about it (e.g., Avoid ggplot sorting the x-axis while plotting geom_bar()).
This may be a duplicate, but I haven't come across this particular situation.
I'm trying to maintain the order of the X-axis variable ("cylinders") in a stacked bar plot. Here's a toy example. I converted the variable below to emphasize the alphabetic ordering on the X axis even though that variable (cylinders) has explicit ordering set earlier in the dataframe as "Four cyl", "Six cyl", and "Eight cyl".
What am I doing wrong?
mtcars <- mtcars %>%
mutate(cylinders = case_when(cyl == 4 ~ "Four cyl",
cyl == 6 ~ "Six cyl",
cyl == 8 ~ "Eight cyl"),
cylinders = reorder(cylinders, cyl, mean)) %>%
mutate(engine = case_when(vs == 1 ~ "Manual",
vs == 0 ~ "Automatic"))
str(mtcars$cylinders)
levels(mtcars$cylinders) # [1] "Four cyl" "Six cyl" "Eight cyl"
class(mtcars$cylinders)
facet_test <- function(df, gathvar) {
gath <- enquo(gathvar)
df %>%
select(cylinders, !!gath) %>%
gather(key, value, -!!gath) %>%
count(!!gath, key, value) %>%
group_by(value) %>%
mutate(perc = round(n/sum(n), 2) * 100) %>%
ggplot(aes(x = value, y = perc, fill = !!gath)) +
geom_bar(stat = "identity")
}
facet_test(df = mtcars, gathvar = engine)
gather
line, you have 3 columns:engine
,key
, andvalue
.value
is where your cylinder information is, but it isn't a factor, so there's no ordering. But I don't see why you need thegather
anyway—you could have made this plot without it – camillegather
and go straight tocount
, then usex = cylinders
in youraes
– camillegather
is there because this is a truncated example of a longer, more complicated function. Any advice on how to make thevalue
column retain the factor information? – Danielvalue
a factor and getting the levels by order of appearance in that column (such as usingforcats::fct_inorder
) – camille