Is there a way to order a legend in ggplot differently than the elements on the plot. for example I want the legend to be ordered Calanoida, Cladocera, Rotifera, and Cyclopoida but I want the ggplot to look the exact same with Calanoida on the bottom of the stacked bars and Cyclopoida on the top.
Thank you in advance. Also if you know how to add spaces in between bars on a stacked group barplot that would be helpful as well. I usually use
geom_bar(stat="identity", position = position_dodge(width = 6))
but the position argument is being used as geom_bar(position = "stack")
when making a stacked bar plot...
Zoop_df_Ab = structure(list(Type = c("Zooplankton", "Zooplankton", "Zooplankton",
"Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton",
"Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton",
"Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton",
"Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton",
"Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton",
"Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton",
"Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton",
"Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton",
"Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton",
"Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton",
"Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton", "Zooplankton",
"Zooplankton", "Zooplankton"), Analysis = c("Abundance", "Abundance",
"Abundance", "Abundance", "Abundance", "Abundance", "Abundance",
"Abundance", "Abundance", "Abundance", "Abundance", "Abundance",
"Abundance", "Abundance", "Abundance", "Abundance", "Abundance",
"Abundance", "Abundance", "Abundance", "Abundance", "Abundance",
"Abundance", "Abundance", "Abundance", "Abundance", "Abundance",
"Abundance", "Abundance", "Abundance", "Abundance", "Abundance",
"Abundance", "Abundance", "Abundance", "Abundance", "Abundance",
"Abundance", "Abundance", "Abundance", "Abundance", "Abundance",
"Abundance", "Abundance", "Abundance", "Abundance", "Abundance",
"Abundance", "Abundance", "Abundance", "Abundance", "Abundance",
"Abundance", "Abundance", "Abundance", "Abundance", "Abundance",
"Abundance", "Abundance", "Abundance"), Lake = structure(c(1L,
1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L, 5L, 5L, 5L, 1L, 1L,
1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L, 5L, 5L, 5L, 1L, 1L, 1L,
2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L, 5L, 5L, 5L, 1L, 1L, 1L, 2L,
2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L, 5L, 5L, 5L), levels = c("Lake N11",
"Area 8", "East Lake", "Lake 3", "Lake D2/D3"), class = "factor"),
Season = structure(c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L,
1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L,
1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L,
1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L,
1L, 2L, 3L, 1L, 2L, 3L), levels = c("July", "August", "September"
), class = "factor"), Class = structure(c(1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L,
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L,
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L), levels = c("Cyclopoida",
"Rotifera", "Cladocera", "Calonoida"), class = "factor"),
Value = c(31.98162171, 36.39715076, 10.4136626, 12.06768565,
38.64860417, 3.742104317, 19.28343448, 51.39177662, 42.69303059,
10.89828073, 37.6923044, 30.19541624, 72.52209628, 76.49344251,
49.13209458, 34.6058036, 34.72740008, 86.59848507, 54.32721503,
56.46492886, 95.39481296, 50.91696935, 34.22043376, 44.75895084,
71.24798268, 47.33509161, 64.89139552, 11.5376884, 8.058506181,
42.18223086, 0.214567442, 0.858128087, 0.859215877, 1.016869217,
0.255412534, 0.254841312, 2.904754731, 1.33692291, 3.971509741,
5.106726241, 3.157013231, 0.874656528, 5.499848364, 0.833803688,
3.943039326, 33.19801615, 28.01733131, 2.128631466, 32.58822874,
4.631055299, 0.608235357, 26.89484164, 13.05085317, 8.576504648,
12.74700931, 11.81559686, 4.038527706, 10.44035937, 14.61425814,
4.742638092)), row.names = c(NA, -60L), class = c("tbl_df",
"tbl", "data.frame"))
Ab_plot_Zoop <- ggplot(Zoop_df_Ab, # Draw barplot with grouping & stacking
aes(x = Lake,
y = Value,
fill = Class)) +
geom_bar(stat = "identity",
position = "stack", width = 0.6) +
geom_vline(data = dat_vline, aes(xintercept = xintercept), lineend = "square") +
geom_hline(data = dat_hline, aes(yintercept = yintercept), lineend = "square") +
theme_classic() + theme(panel.border = element_rect(colour = NA, fill=NA, size=0),
text = element_text(size = 8, family = "sans"),
) + scale_y_continuous(expand = c(0,0)) + labs(x = "", y = expression(paste("Relative Abundance (%)"))) +
facet_wrap(~factor(Season, levels=c('July','August','September')), strip.position = "bottom", scales = "free_x") +
theme(panel.background = element_blank(),
panel.spacing = unit(0, "line"),
strip.background = element_blank(),
strip.placement = "outside") + theme(plot.title.position = 'plot',
plot.title = element_text(hjust = 0.5)) + theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
scale_x_discrete(NULL, expand = c(0.3, 0.3)) + scale_fill_manual(values = c('black', 'lightgrey', 'white','darkgrey')) +
scale_pattern_manual(
"Class",
values = c('none', 'none', 'crosshatch', 'stripe')
) +
scale_pattern_angle_manual(
"Class",
values = c(0,0, 30, 45)
) +
geom_col_pattern(
aes(pattern = Class),
pattern_size = .05,
pattern_density = .1,
pattern_spacing = .02,
pattern_fill = "black",
color = "black",
)
Ab_plot_Zoop
If you specify breaks=
, you can change the order within a legend; this needs to be done for all scales shown in the legend, so it'll be done multiple times.
When doing work like this, I tend to use a data.frame
that matches the Class
values with its scale parameters, such as:
classes <- tibble::tribble(
~Class , ~fill , ~pattern , ~pattern_angle, ~order
, "Calonoida" , "darkgrey" , "stripe" , 45, 1
, "Cladocera" , "white" , "crosshatch", 30, 2
, "Rotifera" , "lightgrey", "none" , 0, 3
, "Cyclopoida", "black" , "none" , 0, 4
)
The use of tribble
is certainly not required to make this frame, I use it here because it shows everything lined up nicely. Also, I added the order
column here because it was convenient to create this table elsewhere and sort into this final form.
The other thing I much prefer to do is to provide named values when using a scale_*_manual
. That is, c(0,0,30,45)
works fine until at some point you change the order of values in your factor
for whatever reason and forget to change the order of these numbers. By using a named-vector, we guard against that silent corruption (in a sense).
I'm commenting out the geom_hline
and geom_vline
since I don't have those data.
This is your original code:
ggplot(Zoop_df_Ab, # Draw barplot with grouping & stacking
aes(x = Lake,
y = Value,
fill = Class)) +
geom_bar(stat = "identity",
position = "stack", width = 0.6) +
# geom_vline(data = dat_vline, aes(xintercept = xintercept), lineend = "square") +
# geom_hline(data = dat_hline, aes(yintercept = yintercept), lineend = "square") +
theme_classic() +
theme(panel.border = element_rect(colour = NA, fill=NA, size=0),
text = element_text(size = 8, family = "sans")) +
scale_y_continuous(expand = c(0,0)) +
labs(x = "", y = expression(paste("Relative Abundance (%)"))) +
facet_wrap(~factor(Season, levels=c('July','August','September')), strip.position = "bottom", scales = "free_x") +
theme(panel.background = element_blank(),
panel.spacing = unit(0, "line"),
strip.background = element_blank(),
strip.placement = "outside") +
theme(plot.title.position = 'plot',
plot.title = element_text(hjust = 0.5)) +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
scale_x_discrete(NULL, expand = c(0.3, 0.3)) +
scale_fill_manual(values = c('black', 'lightgrey', 'white','darkgrey')) +
scale_pattern_manual(
"Class",
values = c('none', 'none', 'crosshatch', 'stripe')
) +
scale_pattern_angle_manual(
"Class",
values = c(0,0, 30, 45)
) +
geom_col_pattern(
aes(pattern = Class),
pattern_size = .05,
pattern_density = .1,
pattern_spacing = .02,
pattern_fill = "black",
color = "black",
)
Here is the updated code with my changes:
ggplot(Zoop_df_Ab, # Draw barplot with grouping & stacking
aes(x = Lake,
y = Value,
fill = Class)) +
geom_bar(stat = "identity",
position = "stack", width = 0.6) +
# geom_vline(data = dat_vline, aes(xintercept = xintercept), lineend = "square") +
# geom_hline(data = dat_hline, aes(yintercept = yintercept), lineend = "square") +
theme_classic() +
theme(panel.border = element_rect(colour = NA, fill=NA, size=0),
text = element_text(size = 8, family = "sans")) +
scale_y_continuous(expand = c(0,0)) +
labs(x = "", y = expression(paste("Relative Abundance (%)"))) +
facet_wrap(~factor(Season, levels=c('July','August','September')), strip.position = "bottom", scales = "free_x") +
theme(panel.background = element_blank(),
panel.spacing = unit(0, "line"),
strip.background = element_blank(),
strip.placement = "outside") +
theme(plot.title.position = 'plot',
plot.title = element_text(hjust = 0.5)) +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
scale_x_discrete(NULL, expand = c(0.3, 0.3)) +
scale_fill_manual(
values = setNames(classes$fill, classes$Class),
breaks = classes$Class
) +
scale_pattern_manual(
"Class",
values = setNames(classes$pattern, classes$Class),
breaks = classes$Class
) +
scale_pattern_angle_manual(
"Class",
values = setNames(classes$pattern_angle, classes$Class),
breaks = classes$Class
) +
geom_col_pattern(
aes(pattern = Class),
pattern_size = .05,
pattern_density = .1,
pattern_spacing = .02,
pattern_fill = "black",
color = "black",
)