Ggplot2: Plotting Order of Factors Within a Geom

ggplot2: plotting order of factors within a geom

When you create the factor variable, you can influence the ordering using the levels parameter

f = factor(c('one', 'two'), levels = c('one', 'two'))
dataset = data.frame(x=1:2, y=1:2, group=f)
p = ggplot(dataset, aes(x,y))
p = p + geom_point(aes(colour = group))

Now, ggplot uses this order for the legend.

Order X axis in ggplot, when there are multiple geoms with different factors

As far as I get it you could achieve your desired result by converting your data to wide format using e.g. tidyr::pivot_wider:


library(tidyr)
library(ggplot2)

ach_wide <- ach %>%
pivot_wider(names_from = "graf", values_from = "pct")

ggplot(data = ach_wide, aes(label, fill = navn)) +
geom_col(aes(y = `All time`),
position = "dodge2"
) +
geom_point(aes(y = `Last month`, color = "1"),
stroke = 2, shape = 21, size = 4, position = position_dodge2(.9)
) +
scale_y_continuous(labels = scales::percent) +
labs(title = "Top 10 browsers", x = "", y = "Pct pageviews", fill = "All time", color = "Last month") +
theme_bw() +
theme(legend.position = "bottom", axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5))
#> Warning: Removed 3 rows containing missing values (geom_col).
#> Warning: Removed 3 rows containing missing values (geom_point).

Sample Image

Ordering ggplot2 legend to agree with factor order of bars in geom_col when plotting data from tabyl

So it turns out the problem was this bit in the geom_col portion of the ggplot code: fill = str_wrap(Category,40). Somehow that fill argument didn't play well with scale_fill_discrete, which is why Jared's initial solution didn't work, but his updated answer gets us most of the way there.

So the solution steps were:

  1. Remove the str_wrap command from the geom_col fill argument.
  2. Add scale_fill_discrete(labels = ~ stringr::str_wrap(.x, width = 40)) to the end of the ggplot code.
  3. Add y = "Category" to the labs element in the ggplot (to override the yucky y axis title that would otherwise result from the reordering command).

Huge thanks to @jared_mamrot for helping me troubleshoot!

Also appropriate citation from another post that offered the solution: How to wrap legend text in ggplot?

library(tidyverse)
library(ggplot2)
library(forcats)
library(janitor)
#>
#> Attaching package: 'janitor'
#> The following objects are masked from 'package:stats':
#>
#> chisq.test, fisher.test

temp <- tribble(
~ Category,
"AAAAAAA AAAAAAAA AAAAAAAAA AAAAAAAAAA AAAAAAAAAAA AAAAAAAAAAA AAAAAAAA AAAAAAAAAA",
"AAAAAAA AAAAAAAA AAAAAAAAA AAAAAAAAAA AAAAAAAAAAA AAAAAAAAAAA AAAAAAAA AAAAAAAAAA",
"AAAAAAA AAAAAAAA AAAAAAAAA AAAAAAAAAA AAAAAAAAAAA AAAAAAAAAAA AAAAAAAA AAAAAAAAAA",
"AAAAAAA AAAAAAAA AAAAAAAAA AAAAAAAAAA AAAAAAAAAAA AAAAAAAAAAA AAAAAAAA AAAAAAAAAA",
"AAAAAAA AAAAAAAA AAAAAAAAA AAAAAAAAAA AAAAAAAAAAA AAAAAAAAAAA AAAAAAAA AAAAAAAAAA",
"AAAAAAA AAAAAAAA AAAAAAAAA AAAAAAAAAA AAAAAAAAAAA AAAAAAAAAAA AAAAAAAA AAAAAAAAAA",
"AAAAAAA AAAAAAAA AAAAAAAAA AAAAAAAAAA AAAAAAAAAAA AAAAAAAAAAA AAAAAAAA AAAAAAAAAA",
"AAAAAAA AAAAAAAA AAAAAAAAA AAAAAAAAAA AAAAAAAAAAA AAAAAAAAAAA AAAAAAAA AAAAAAAAAA",
"AAAAAAA AAAAAAAA AAAAAAAAA AAAAAAAAAA AAAAAAAAAAA AAAAAAAAAAA AAAAAAAA AAAAAAAAAA",
"AAAAAAA AAAAAAAA AAAAAAAAA AAAAAAAAAA AAAAAAAAAAA AAAAAAAAAAA AAAAAAAA AAAAAAAAAA",
"BBBB BBBB BBBBB B BBBBBB BBBBB BBBBBB BBBBB BBBBB B BBBB BBBBB BBBBBBB",
"BBBB BBBB BBBBB B BBBBBB BBBBB BBBBBB BBBBB BBBBB B BBBB BBBBB BBBBBBB",
"BBBB BBBB BBBBB B BBBBBB BBBBB BBBBBB BBBBB BBBBB B BBBB BBBBB BBBBBBB",
"BBBB BBBB BBBBB B BBBBBB BBBBB BBBBBB BBBBB BBBBB B BBBB BBBBB BBBBBBB",
"BBBB BBBB BBBBB B BBBBBB BBBBB BBBBBB BBBBB BBBBB B BBBB BBBBB BBBBBBB",
"BBBB BBBB BBBBB B BBBBBB BBBBB BBBBBB BBBBB BBBBB B BBBB BBBBB BBBBBBB",
"BBBB BBBB BBBBB B BBBBBB BBBBB BBBBBB BBBBB BBBBB B BBBB BBBBB BBBBBBB",
"BBBB BBBB BBBBB B BBBBBB BBBBB BBBBBB BBBBB BBBBB B BBBB BBBBB BBBBBBB",
"BBBB BBBB BBBBB B BBBBBB BBBBB BBBBBB BBBBB BBBBB B BBBB BBBBB BBBBBBB",
"BBBB BBBB BBBBB B BBBBBB BBBBB BBBBBB BBBBB BBBBB B BBBB BBBBB BBBBBBB",
"BBBB BBBB BBBBB B BBBBBB BBBBB BBBBBB BBBBB BBBBB B BBBB BBBBB BBBBBBB",
"BBBB BBBB BBBBB B BBBBBB BBBBB BBBBBB BBBBB BBBBB B BBBB BBBBB BBBBBBB",
"CCCCC CCC CCC CC CCCCC CCC CCCCCCCCCC CCCC CCCCC CCCCCCCCC CCCCCCCCCCC CCCC CCC CCC C CCC",
"CCCCC CCC CCC CC CCCCC CCC CCCCCCCCCC CCCC CCCCC CCCCCCCCC CCCCCCCCCCC CCCC CCC CCC C CCC",
"CCCCC CCC CCC CC CCCCC CCC CCCCCCCCCC CCCC CCCCC CCCCCCCCC CCCCCCCCCCC CCCC CCC CCC C CCC",
"CCCCC CCC CCC CC CCCCC CCC CCCCCCCCCC CCCC CCCCC CCCCCCCCC CCCCCCCCCCC CCCC CCC CCC C CCC",
"DDDDD DD D DDD DDDD DDD DDDDDDD DDD DDDD DDDDDDD DDD DDD DDDD DDDDDDDDD DDDD DDDDD DDDDDDD",
"DDDDD DD D DDD DDDD DDD DDDDDDD DDD DDDD DDDDDDD DDD DDD DDDD DDDDDDDDD DDDD DDDDD DDDDDDD",
"DDDDD DD D DDD DDDD DDD DDDDDDD DDD DDDD DDDDDDD DDD DDD DDDD DDDDDDDDD DDDD DDDDD DDDDDDD",
"DDDDD DD D DDD DDDD DDD DDDDDDD DDD DDDD DDDDDDD DDD DDD DDDD DDDDDDDDD DDDD DDDDD DDDDDDD",
"DDDDD DD D DDD DDDD DDD DDDDDDD DDD DDDD DDDDDDD DDD DDD DDDD DDDDDDDDD DDDD DDDDD DDDDDDD",
"DDDDD DD D DDD DDDD DDD DDDDDDD DDD DDDD DDDDDDD DDD DDD DDDD DDDDDDDDD DDDD DDDDD DDDDDDD",
"DDDDD DD D DDD DDDD DDD DDDDDDD DDD DDDD DDDDDDD DDD DDD DDDD DDDDDDDDD DDDD DDDDD DDDDDDD",
"DDDDD DD D DDD DDDD DDD DDDDDDD DDD DDDD DDDDDDD DDD DDD DDDD DDDDDDDDD DDDD DDDDD DDDDDDD",
"DDDDD DD D DDD DDDD DDD DDDDDDD DDD DDDD DDDDDDD DDD DDD DDDD DDDDDDDDD DDDD DDDDD DDDDDDD",
"DDDDD DD D DDD DDDD DDD DDDDDDD DDD DDDD DDDDDDD DDD DDD DDDD DDDDDDDDD DDDD DDDDD DDDDDDD",
"DDDDD DD D DDD DDDD DDD DDDDDDD DDD DDDD DDDDDDD DDD DDD DDDD DDDDDDDDD DDDD DDDDD DDDDDDD",
"DDDDD DD D DDD DDDD DDD DDDDDDD DDD DDDD DDDDDDD DDD DDD DDDD DDDDDDDDD DDDD DDDDD DDDDDDD",
"DDDDD DD D DDD DDDD DDD DDDDDDD DDD DDDD DDDDDDD DDD DDD DDDD DDDDDDDDD DDDD DDDDD DDDDDDD",
"DDDDD DD D DDD DDDD DDD DDDDDDD DDD DDDD DDDDDDD DDD DDD DDDD DDDDDDDDD DDDD DDDDD DDDDDDD",
"DDDDD DD D DDD DDDD DDD DDDDDDD DDD DDDD DDDDDDD DDD DDD DDDD DDDDDDDDD DDDD DDDDD DDDDDDD",
"DDDDD DD D DDD DDDD DDD DDDDDDD DDD DDDD DDDDDDD DDD DDD DDDD DDDDDDDDD DDDD DDDDD DDDDDDD",
"EEEE",
"EEEE",
"EEEE",
"EEEE",
)

temp_n <- temp %>%
nrow()

temp_tabyl <-
temp %>%
tabyl(Category) %>%
mutate(Category = factor(Category,levels = c("DDDDD DD D DDD DDDD DDD DDDDDDD DDD DDDD DDDDDDD DDD DDD DDDD DDDDDDDDD DDDD DDDDD DDDDDDD",
"BBBB BBBB BBBBB B BBBBBB BBBBB BBBBBB BBBBB BBBBB B BBBB BBBBB BBBBBBB",
"AAAAAAA AAAAAAAA AAAAAAAAA AAAAAAAAAA AAAAAAAAAAA AAAAAAAAAAA AAAAAAAA AAAAAAAAAA",
"CCCCC CCC CCC CC CCCCC CCC CCCCCCCCCC CCCC CCCCC CCCCCCCCC CCCCCCCCCCC CCCC CCC CCC C CCC",
"EEEE"))) %>%
rename(Percent = percent) %>%
arrange(desc(Percent)) %>%
mutate(CI = sqrt(Percent*(1-Percent)/temp_n),
MOE = CI * 1.96,
ub = Percent + MOE,
lb = Percent - MOE)

temp_tabyl %>%
ggplot() +
geom_col(aes(y = reorder(Category,Percent),
x = Percent,
fill = Category),
colour = "black"
) +
geom_errorbar(
aes(
y = reorder(Category,Percent),
xmin = lb,
xmax = ub
),
width = 0.4,
colour = "orange",
alpha = 0.9,
size = 1.3
) +
labs(colour="Category",
y = "Category") +
geom_label(aes(y = Category,
x = Percent,
label = scales::percent(Percent)),nudge_x = .11) +
scale_x_continuous(labels = scales::percent,limits = c(0,1)) +
labs(title = "Plot Title",
caption = "Plot Caption.") +
theme_bw() +
theme(
text = element_text(family = 'Roboto'),
strip.text.x = element_text(size = 14,
face = 'bold'),
panel.grid.minor = element_blank(),
axis.title.y = element_text(size = 14),
plot.title = element_text(hjust = 0.5, size = 16),
plot.subtitle = element_text(hjust = 1),
plot.caption = element_text(hjust = 0),
axis.text.y=element_blank()
) +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank()) +
theme(strip.text = element_text(colour = 'white'),
legend.spacing.y = unit(.5, 'cm')) +
guides(fill = guide_legend(as.factor('Category'),
byrow = TRUE)) +
scale_fill_discrete(labels = ~ stringr::str_wrap(.x, width = 40))

Sample Image

Created on 2022-06-20 by the reprex package (v2.0.1)

How to maintain factor orders when using geom_point and geom_pointrange in one plot?

Are you looking for something like this ?

I started by generating a second dataframe with calculated mean of each site, that I add this as additional rows of the original dataset. I re-organized levels of factor Samples and Site. I finally passed it into ggplot using geom_point and geom_errorbar:

library(dplyr)
library(ggplot2)

Mean_DF <- benthic_data %>%
group_by(Site) %>%
summarise(Mean = mean(Abundance), SD = sd(Abundance)) %>%
mutate(Sample = c("S-27-Mean","S-7-Mean")) %>% rename(Abundance = Mean)

benthic_data %>% select(Site, Sample, Abundance) %>% bind_rows(., Mean_DF) %>%
mutate(Site = factor(Site, levels = c("S-7","S-27"))) %>%
mutate(Sample = factor(Sample, levels=c('S-7-1', 'S-7-2','S-7-3','S-7-4','S-7-5','S-7-Mean','S-27-1','S-27-2','S-27-3','S-27-4', 'S-27-5','S-27-Mean'))) %>%
ggplot(aes(x = Sample, y = Abundance, color = Site))+
geom_point()+
geom_errorbar(aes(ymin = Abundance-SD, ymax = Abundance+SD), width = 0.2)+
scale_color_manual(values = c("darkgreen", "orangered3"))

Sample Image

Custom order of legend in ggplot2 so it doesn't match the order of the factor in the plot

Unfortunately, I could not reproduce your figure fully as it seems that I'm missing your med data.

However, changing the levels in your data frame accordingly should do the trick. Just do the following before the ggplot() command:

levels(df$value) <- c("Very Important", "Important", "Less Important", 
"Not at all Important", "Strongly Satisfied",
"Satisfied", "Strongly Dissatisfied", "Dissatisified", "N/A")

Edit

Being able to reproduce your example, I came up with the following, a bit hacky, solution.

p <- ggplot(df, aes(x=Benefit, y = Percent, fill = value, label=abs(Percent))) +
geom_bar(stat="identity", width = .5, position = position_stack(reverse = TRUE)) +
geom_col(position = 'stack') +
scale_x_discrete(limits = rev(levels(df$Benefit))) +
geom_text(position = position_stack(vjust = 0.5),
angle = 45, color="black") +
coord_flip() +
scale_fill_manual(labels = c("Very Important", "Important", "Less Important",
"Not at all Important", "Strongly Satisfied",
"Satisfied", "N/A"),values = col4) +
scale_y_continuous(breaks=(seq(-100,100,25)), labels=abs(seq(-100,100,by=25)), limits=c(-100,100)) +
theme_minimal() +
theme(
axis.title.y = element_blank(),
legend.position = c(0.85, 0.8),
legend.title=element_text(size=14),
axis.text=element_text(size=12, face="bold"),
legend.text=element_text(size=12),
panel.background = element_rect(fill = "transparent",colour = NA),
plot.background = element_rect(fill = "transparent",colour = NA),
#panel.border=element_blank(),
panel.grid.major=element_blank(),
panel.grid.minor=element_blank()
)+
labs(fill="") + ylab("") + ylab("Percent") +
annotate("text", x = 9.5, y = 50, label = "Importance") +
annotate("text", x = 8.00, y = 50, label = "Satisfaction") +
guides(fill = guide_legend(override.aes = list(fill = c("#81A88D","#ABDDDE","#F4B5BD","#B40F20","orange","#F3DF6C","gray")) ) )
p

Sample Image



Related Topics



Leave a reply



Submit