Reputation: 51
So I have this bar chart I made using:
ggplot(ViralReads, aes(x=Host, y=Reads, fill=Taxon)) +
geom_col(colour = "black", position = "fill") +
scale_y_continuous(labels = label_percent())+
theme_minimal()
For each "taxon" there is a category 'Genome' associated with it. I would like to group the items in the legend by 'Genome'. Anyone know if this is possible to do? I tried to play around with the legend a
Here is reproducible data as requested!
structure(list(Host = c("Culex", "Culex", "Culex", "Culex", "Culex",
"Culex", "Culex", "Culex", "Culex", "Culex", "Culex", "Culex",
"Culex", "Culex", "Culex", "Culex", "Culex", "Culex", "Culex",
"Culex", "Culex", "Culex", "Culex", "Aedes", "Aedes", "Aedes",
"Aedes", "Aedes", "Aedes", "Aedes", "Aedes", "Aedes", "Aedes",
"Aedes", "Aedes", "Aedes", "Aedes", "Aedes", "Aedes", "Aedes",
"Aedes", "Aedes", "Aedes", "Aedes", "Aedes", "Aedes", "Ochlerotatus",
"Ochlerotatus", "Ochlerotatus", "Ochlerotatus", "Ochlerotatus",
"Ochlerotatus", "Ochlerotatus", "Ochlerotatus", "Ochlerotatus",
"Ochlerotatus", "Ochlerotatus", "Ochlerotatus", "Ochlerotatus",
"Ochlerotatus", "Ochlerotatus", "Ochlerotatus", "Ochlerotatus",
"Ochlerotatus", "Ochlerotatus", "Ochlerotatus", "Ochlerotatus",
"Ochlerotatus", "Ochlerotatus", "Coquillettidia", "Coquillettidia",
"Coquillettidia", "Coquillettidia", "Coquillettidia", "Coquillettidia",
"Coquillettidia", "Coquillettidia", "Coquillettidia", "Coquillettidia",
"Coquillettidia", "Coquillettidia", "Coquillettidia", "Coquillettidia",
"Coquillettidia", "Coquillettidia", "Coquillettidia", "Coquillettidia",
"Coquillettidia", "Coquillettidia", "Coquillettidia", "Coquillettidia",
"Coquillettidia"), Genome = c("(-)ssRNA", "(-)ssRNA", "(-)ssRNA",
"(-)ssRNA", "(-)ssRNA", "(-)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA",
"(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA",
"(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "dsRNA", "dsRNA",
"dsRNA", "ssDNA", "(-)ssRNA", "(-)ssRNA", "(-)ssRNA", "(-)ssRNA",
"(-)ssRNA", "(-)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA",
"(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA",
"(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "dsRNA", "dsRNA", "dsRNA",
"ssDNA", "(-)ssRNA", "(-)ssRNA", "(-)ssRNA", "(-)ssRNA", "(-)ssRNA",
"(-)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA",
"(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA",
"(+)ssRNA", "(+)ssRNA", "dsRNA", "dsRNA", "dsRNA", "ssDNA", "(-)ssRNA",
"(-)ssRNA", "(-)ssRNA", "(-)ssRNA", "(-)ssRNA", "(-)ssRNA", "(+)ssRNA",
"(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA",
"(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA", "(+)ssRNA",
"dsRNA", "dsRNA", "dsRNA", "ssDNA"), Reads = c(102317, 163616,
6188, 130, 0, 0, 195632, 38928, 51823, 4033, 71500, 0, 0, 102317,
3953, 363, 52677, 62, 4033, 5183, 1542, 0, 4313, 1071, 36260,
0, 10089, 0, 0, 84154, 0, 814, 0, 82223, 281910, 60584, 1071,
8802, 0, 2203, 0, 0, 0, 622680, 0, 2229, 0, 0, 0, 550, 0, 0,
1445303, 0, 0, 0, 960293, 16515, 470781, 0, 0, 701, 0, 0, 0,
0, 0, 0, 0, 352, 0, 0, 0, 0, 1186, 138498, 200, 0, 197, 2640,
0, 0, 352, 0, 0, 0, 0, 197, 0, 3752, 0, 10899), Taxon = c("Orthomyxoviridae",
"Rhabdoviridae", "Peribunyaviridae", "Chuviridae", "Phasmaviridae",
"Phenuiviridae", "Iflaviridae", "Luteoviridae", "Tombusviridae",
"Nodaviridae", "Unclassified Picornavirales", "Negevirus", "Tymoviridae",
"Virgaviridae", "Dicistroviridae", "Totiviridae", "Flaviviridae",
"Narnaviridae", "Nodaviridae", "Partitiviridae", "Birnaviridae",
"Reoviridae", "Parvoviridae", "Orthomyxoviridae", "Rhabdoviridae",
"Peribunyaviridae", "Chuviridae", "Phasmaviridae", "Phenuiviridae",
"Iflaviridae", "Luteoviridae", "Tombusviridae", "Nodaviridae",
"Unclassified Picornavirales", "Negevirus", "Tymoviridae", "Virgaviridae",
"Dicistroviridae", "Totiviridae", "Flaviviridae", "Narnaviridae",
"Nodaviridae", "Partitiviridae", "Birnaviridae", "Reoviridae",
"Parvoviridae", "Orthomyxoviridae", "Rhabdoviridae", "Peribunyaviridae",
"Chuviridae", "Phasmaviridae", "Phenuiviridae", "Iflaviridae",
"Luteoviridae", "Tombusviridae", "Nodaviridae", "Unclassified Picornavirales",
"Negevirus", "Tymoviridae", "Virgaviridae", "Dicistroviridae",
"Totiviridae", "Flaviviridae", "Narnaviridae", "Nodaviridae",
"Partitiviridae", "Birnaviridae", "Reoviridae", "Parvoviridae",
"Orthomyxoviridae", "Rhabdoviridae", "Peribunyaviridae", "Chuviridae",
"Phasmaviridae", "Phenuiviridae", "Iflaviridae", "Luteoviridae",
"Tombusviridae", "Nodaviridae", "Unclassified Picornavirales",
"Negevirus", "Tymoviridae", "Virgaviridae", "Dicistroviridae",
"Totiviridae", "Flaviviridae", "Narnaviridae", "Nodaviridae",
"Partitiviridae", "Birnaviridae", "Reoviridae", "Parvoviridae"
)), row.names = c(NA, -92L), class = c("tbl_df", "tbl", "data.frame"
))
Upvotes: 1
Views: 1172
Reputation: 174586
The short answer here is "no", you can't have grouped legends within ggplot natively.
However, the long answer is "yes, but it isn't easy". It requires creating a bunch of plots (one per genome) and harvesting their legends, then stitching them back onto the main plot:
library(tidyverse)
fill_df <- ViralReads %>%
select(-1, -3) %>%
unique() %>%
mutate(color = scales::hue_pal()(22))
legends <- lapply(split(ViralReads, ViralReads$Genome), function(x) {
genome <- x$Genome[1]
patchwork::wrap_elements(full = cowplot::get_legend(
ggplot(x, aes(Host, Reads, fill = Taxon)) +
geom_col(color = "black") +
scale_fill_manual(
name = genome,
values = setNames(fill_df$color[fill_df$Genome == genome],
fill_df$Taxon[fill_df$Genome == genome])) +
theme(legend.justification = c(0, 1))))
})
p1 <- ggplot(ViralReads, aes(x=Host, y=Reads, fill=Taxon)) +
geom_col(colour = "black", position = "fill") +
scale_y_continuous(labels = scales::label_percent())+
theme_minimal() +
theme(legend.position = "none")
p1 + ((legends[[1]] + legends[[2]]) / (legends[[3]] + legends[[4]]))
Unfortunately, 22 different colors is just too many to use as a discrete color scale. I would probably use a different way of visualising these data, perhaps something like this:
library(tidyverse)
ViralReads %>%
filter(Reads > 0) %>%
mutate(Taxon = sub("Unclassified", "misc", Taxon)) %>%
mutate(Taxon = reorder(factor(Taxon), as.numeric(factor(Genome)))) %>%
ggplot(aes(Taxon, Reads, fill = Genome)) +
geom_col() +
scale_y_log10(labels = scales::comma, name = "Reads (log scale)") +
facet_wrap(.~Host, scales = "free_x") +
scale_fill_brewer(palette = "Set1") +
theme_minimal(base_size = 16) +
theme(axis.text.x = element_text(angle = 90, hjust = 1, size = 8),
strip.text = element_text(face = "bold"),
panel.border = element_rect(fill = NA, color = "gray90"))
Anyway, it's good to know that grouped legends are at least possible in ggplot, so thanks for the OP.
Upvotes: 3