Based on the data and code below, how can I change of the legend items such that the legend item Males
is under the Male portion
of the pyramid plot
and vice versa?
I tried:
# Change the order of values to reflect them in the plot
pop_hisp_df$Type = factor(pop_hisp_df$Type, levels = rev(pop_hisp_df$Type))
Error in `levels<-`(`*tmp*`, value = as.character(levels)) :
factor level [2] is duplicated
Current Output:
Data (pop_hisp_df
):
structure(list(age_group = c("< 5 years", "5 - 14", "15 - 24",
"25 - 34", "35 - 44", "45 - 54", "55 - 64", "65 - 74",
"75 - 84", "85 ", "< 5 years", "5 - 14", "15 - 24", "25 - 34",
"35 - 44", "45 - 54", "55 - 64", "65 - 74", "75 - 84",
"85 "), Type = c("Males", "Males", "Males", "Males", "Males",
"Males", "Males", "Males", "Males", "Males", "Females", "Females",
"Females", "Females", "Females", "Females", "Females", "Females",
"Females", "Females"), Value = c(-6, -13, -13, -15, -17, -15,
-11, -6, -3, -1, 6, 12, 12, 14, 16, 15, 12, 7, 4, 2)), row.names = c(NA,
-20L), class = c("tbl_df", "tbl", "data.frame"))
Code:
library(tidyverse)
library(plotly)
# Plot
gg_pop_hisp = ggplot(pop_hisp_df, aes( x = forcats::as_factor(age_group), y = Value, fill = Type))
geom_bar(data = subset(pop_hisp_df, Type == "Females"), stat = "identity")
geom_bar(data = subset(pop_hisp_df, Type == "Males"), stat = "identity")
#geom_text(aes(label = paste0(abs(Value), "%")))
scale_y_continuous(limits=c(-20,20),
breaks=c(-15,-10,0,10,15),
labels=paste0(c(15,10,0,10,15),"%")) # CHANGE
scale_fill_manual(name = "", values = c("Females"="#FC921F", "Males"="#149ECE"), labels = c("Females", "Males"))
ggtitle("HISPANIC POPULATION BY GENDER AND AGE GROUP")
labs(x = "AGE GROUPS", y = "PERCENTAGE POPULATION", fill = "Gender")
theme_minimal()
theme(legend.position="bottom")
coord_flip()
# Interactive
ggplotly(gg_pop_hisp) %>%
layout(
legend = list(
orientation = 'h', x = 0.3, y = -0.3,
title = list(text = '')))
CodePudding user response:
Solution for ggplotly Only
In this case, simply swapping the calls to geom_bar
(i.e create bars for Males at first and then for Females) creates the desired output, which is a lot simpler.
gg_pop_hisp = ggplot(pop_hisp_df, aes( x = forcats::as_factor(age_group), y = Value, fill = Type))
geom_bar(data = subset(pop_hisp_df, Type == "Males"), stat = "identity")
geom_bar(data = subset(pop_hisp_df, Type == "Females"), stat = "identity")
#geom_text(aes(label = paste0(abs(Value), "%")))
scale_y_continuous(limits=c(-20,20),
breaks=c(-15,-10,0,10,15),
labels=paste0(c(15,10,0,10,15),"%"))
scale_fill_manual(name = "", values = c("Females"="#FC921F", "Males"="#149ECE"), labels = c("Females", "Males"))
ggtitle("HISPANIC POPULATION BY GENDER AND AGE GROUP")
labs(x = "AGE GROUPS", y = "PERCENTAGE POPULATION", fill = "Gender")
theme_minimal()
theme(legend.position="bottom")
coord_flip()
gg_pop_hisp
# Interactive
ggplotly(gg_pop_hisp) %>%
layout(
legend = list(
orientation = 'h', x = 0.3, y = -0.3,
title = list(text = '')))
ggplotly Output
Its works because, the bar for Males
are created at first, so the legend is and similarly thereafter for Females
and therefore, ggplotly
renders the legend in this order.
Solution for both ggplot2 and ggplotly
Note that, in the intermediate ggplot
plot gg_pop_hisp
the issue of misplaced legend still remains. To solve this case both for ggplot
and ggplotly
output,
Create factor variable labels
with levels as Levels: Males Females
and use that scale_fill_manual
to specify the labels
of the scale and also change the order of values
.
labels = forcats::as_factor(c("Males", "Females"))
gg_pop_hisp = ggplot(pop_hisp_df, aes( x = forcats::as_factor(age_group), y = Value, fill = Type))
geom_bar(data = subset(pop_hisp_df, Type == "Males"), stat = "identity")
geom_bar(data = subset(pop_hisp_df, Type == "Females"), stat = "identity")
#geom_text(aes(label = paste0(abs(Value), "%")))
scale_y_continuous(limits=c(-20,20),
breaks=c(-15,-10,0,10,15),
labels=paste0(c(15,10,0,10,15),"%"))
scale_fill_manual(name = "", values = c("Males"="#149ECE", "Females"="#FC921F"), # awapped the order here
labels = labels)
ggtitle("HISPANIC POPULATION BY GENDER AND AGE GROUP")
labs(x = "AGE GROUPS", y = "PERCENTAGE POPULATION", fill = "Gender")
theme_minimal()
theme(legend.position="bottom")
coord_flip()
ggplot2 output
gg_pop_hisp
and the ggplotly output in this case,
ggplotly(gg_pop_hisp) %>%
layout(
legend = list(
orientation = 'h', x = 0.3, y = -0.3,
title = list(text = '')))