I am sure this is a very fix for someone who has done it before. I want to have a different spacing between legend key box 2 and 3 in ggplot2. Is there any trick to have a different spacing between the boxes of the legend? I also want to match the color of the legend box and the text. Currently, the legend text is black. So, I have two questions here
library(tidyverse)
library(ggplot2)
library(ggtext)
Food = c("meat", "meat", "meat", "meat", "wheat","wheat","wheat",
"wheat", "maize","maize","maize","maize")
Subgroup = c("Male", "Female", "Urban", "Rural", "Male", "Female",
"Urban", "Rural", "Male", "Female","Urban", "Rural")
mean = c(8.66, 10.45, 9.88, 7.32, 21.04, 19.65, 20.26, 20.87, 51.06 , 44.51, 47.60, 48.40)
df <- data.frame(Food, Subgroup, mean)
df$Subgroup[df$Subgroup == "Urban"] <- 1
df$Subgroup[df$Subgroup == "Rural"] <- 2
df$Subgroup[df$Subgroup == "Female"] <- 3
df$Subgroup[df$Subgroup == "Male"] <- 4
df$Subgroup <- factor(df$Subgroup,
levels = c(1, 2, 3, 4),
labels = c("Urban", "Rural", "Female", "Male"))
#Color code
colorPanel = c( '#42235e', '#7d103d', '#007da5', '#003b5d' )
# bar chart
Plot_FBGDS <- ggplot(df, aes(x = Food, y = mean, fill = Subgroup)) +
geom_col(stat = "identity", position = position_dodge(-0.84), width = 0.82) +
scale_y_continuous(breaks = c(0,20, 40, 60,80), expand = c(0,0),
limits = c(0,100),
labels = function(x) paste0(x, "%")) +
geom_text(aes(label = paste0(mean,"%"), y = mean + 2, color = Subgroup), stat = "identity",
size = 3, vjust = 0.5, face = "bold", family = "sans", position = position_dodge(-0.88)) +
scale_color_manual(values = colorPanel) +
scale_x_discrete(limits = c("meat",
"wheat",
"maize")) +
coord_flip() +
scale_fill_manual(values = colorPanel) +
labs( x= " ",
y = " ") +
theme(text = element_text(size = 14, color = "black", family = "sans"),
panel.background = element_rect(fill = "white"),
panel.border = element_blank(),
axis.text.y = element_text(family = "sans", color = "black", size = 14),
axis.text.x = element_blank(),
axis.line.x = element_blank(),
axis.line.y = element_line(),
axis.ticks.y.left = element_line(colour = "green"),
axis.ticks.length=unit(0, "cm"),
axis.title.x = element_text(size = 10, color = "black", family = "sans"),
axis.text = element_text(size = 10, color = "black",family = "sans"),
legend.key = element_rect(colour = NA, fill=NA, size= 7),
legend.text = element_text(size = 10, family = "sans"),
legend.margin=margin(t= -1, r= 2, b= 2, l= 2),
legend.title = element_blank(),
legend.key.height = unit(0.03, "npc"),
legend.key.width = unit(0.03, "npc"),
legend.position = c(0.85, 0.70),
panel.grid.major.x = element_blank(),
panel.grid.minor.y = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor.x = element_blank())
Plot_FBGDS
One option would be the ggnewscale
package which allows to add a second fill legend. Doing so we could draw separate legends for Urban/Rural and for Male/Female for which the spacing could be set via legend.spacing.y
. To make this work we have to add a duplicated geom_col
where we have to explicitly map on the fill
aes.
To color the legend text according to the bars you could make use of the ggtext
package which allows styling of text via markdown, HTML and CSS.To this end use ggtext::element_markdown
for legend.text
and add labels
to the legends where you set your desired colors using some HTML and CSS.
library(ggplot2)
library(ggtext)
# Color code
colorPanel <- c("#42235e", "#7d103d", "#007da5", "#003b5d")
names(colorPanel) <- c("Urban", "Rural", "Female", "Male")
labels <- paste0("<span style='color:", colorPanel, ";'>", names(colorPanel), "</span>")
names(labels) <- names(colorPanel)
# bar chart
library(ggnewscale)
Plot_FBGDS <- ggplot(df, aes(x = Food, y = mean, fill = Subgroup)) +
geom_col(position = position_dodge(-0.84), width = 0.82) +
geom_text(aes(label = paste0(mean, "%"), y = mean + 1, color = Subgroup),
size = 3, hjust = 0, vjust = 0.5, fontface = "bold", family = "sans", position = position_dodge(-0.88), show.legend = FALSE
) +
scale_fill_manual(values = colorPanel, breaks = c("Urban", "Rural"), labels = labels[c("Urban", "Rural")],
aesthetics = c("color", "fill"),
guide = guide_legend(order = 1)) +
new_scale_fill() +
new_scale_color() +
geom_col(aes(fill = Subgroup), position = position_dodge(-0.84), width = 0.82) +
scale_fill_manual(values = colorPanel, breaks = c("Female", "Male"), labels = labels[c("Female", "Male")],
aesthetics = c("color", "fill"),
guide = guide_legend(order = 2)) +
scale_y_continuous(
breaks = c(0, 20, 40, 60, 80), expand = c(0, 0),
limits = c(0, 100),
labels = function(x) paste0(x, "%")
) +
scale_x_discrete(limits = c(
"meat",
"wheat",
"maize"
)) +
coord_flip() +
labs(x = " ", y = " ") +
theme(
text = element_text(size = 14, color = "black", family = "sans"),
panel.background = element_rect(fill = "white"),
panel.border = element_blank(),
axis.text.y = element_text(family = "sans", color = "black", size = 14),
axis.text.x = element_blank(),
axis.line.x = element_blank(),
axis.line.y = element_line(),
axis.ticks.y.left = element_line(colour = "green"),
axis.ticks.length = unit(0, "cm"),
axis.title.x = element_text(size = 10, color = "black", family = "sans"),
axis.text = element_text(size = 10, color = "black", family = "sans"),
legend.text = element_markdown(size = 10, family = "sans"),
legend.key = element_rect(colour = NA, fill = NA, size = 7),
legend.key.height = unit(0.03, "npc"),
legend.key.width = unit(0.03, "npc"),
legend.margin = margin(t = -1, r = 2, b = 2, l = 2),
legend.title = element_blank(),
legend.position = c(0.85, 0.70),
legend.spacing.y = unit(2, "pt"),
panel.grid.major.x = element_blank(),
panel.grid.minor.y = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor.x = element_blank()
)
Plot_FBGDS
#> Warning: position_dodge requires non-overlapping x intervals
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.