Reputation: 323
I want to create a density chart showing the distribution of the variable "approval_gov". Now I want to have dashed lines showing the mean of all respondents, plus the means of different independent variables like gender, age cohorts and income levels. The labels should include the mean and the name of the group (e.g. Male: mean). Or they should include only the means and the group name in a legend. I tried several approchaes, but I only managed to get a dashed line for the mean in general, but without any label.
These are the first 20 rows:
lebanon <- structure(list(gender = structure(c(2L, 1L, 1L, 2L, 2L, 2L, 2L,
2L, 2L, 2L, 1L, 2L, 2L, 1L, 2L, 1L, 1L, 2L, 1L, 1L), .Label = c("Female",
"Male"), class = "factor"), approval_gov = c(9L, 7L, 8L, 6L,
6L, 4L, 0L, 0L, 0L, 1L, 5L, 2L, 4L, 2L, 4L, 0L, 0L, 4L, 2L, 2L
), age_cat = structure(c(3L, 2L, 2L, 1L, 1L, 2L, 2L, 3L, 5L,
1L, 1L, 1L, 1L, 3L, 2L, 2L, 1L, 3L, 1L, 4L), .Label = c("18-29",
"30-39", "40-49", "50-59", "60 and above"), class = "factor"),
income_recoded = structure(c(2L, 1L, 1L, 1L, 1L, 1L, 2L,
2L, 1L, 3L, 2L, 2L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 2L), .Label = c("Low income",
"Middle income", "High income", "Don't know"), class = "factor")), row.names = c(NA,
20L), class = "data.frame")
I managed to get this far, but then everything messes up when I try to add labels and group means of several columns in addition the overall mean:
lebanon %>%
filter(!is.na(approval_gov)) %>%
ggplot(aes(approval_gov)) +
geom_density(fill = "steelblue", alpha = 0.5) +
geom_vline(aes(xintercept=mean(approval_gov), color = approval_gov),
color="blue", linetype="dashed", size=1) +
scale_y_continuous(labels = scales::percent) +
scale_x_continuous(breaks = c(0:10)) +
labs(title = " To what extent are you satisfied with the current government's performance?",
x = "", y = "", fill = "") +
theme_minimal() +
theme(legend.text = element_text(size = 20),
plot.title = element_text(size = 32, hjust = 0),
axis.title = element_blank(),
axis.text = element_text(size = 20, colour = "black"),
axis.ticks.y = element_line(),
panel.border = element_rect(colour = "black", fill = NA),
panel.grid.minor = element_blank(),
panel.grid.major = element_blank())
Any suggestions? :)
Greetings
Upvotes: 0
Views: 499
Reputation: 124013
This can be achieved like so. Compute the wanted means and put them in one dataframe together with the group_labels. This dataframe can then be used both with geom_vline
and geom_text
(or ggrepel::geom_label_repel
) to draw the lines and add the labels. Try this:
library(dplyr)
library(ggplot2)
means <- list(
all = summarise(lebanon, value = mean(approval_gov, na.rm = TRUE)) %>% mutate(group = "all"),
gender = group_by(lebanon, gender) %>% summarise(value = mean(approval_gov, na.rm = TRUE)) %>% rename(group = gender),
age_cat = group_by(lebanon, age_cat) %>% summarise(value = mean(approval_gov, na.rm = TRUE)) %>% rename(group = age_cat)) %>%
bind_rows()
lebanon %>%
filter(!is.na(approval_gov)) %>%
ggplot(aes(approval_gov)) +
geom_density(fill = "steelblue", alpha = 0.5) +
geom_vline(data = means, aes(xintercept=value, color = group),
linetype="dashed", size=1, show.legend = FALSE) +
ggrepel::geom_label_repel(data = means, aes(x = value, y = .05, label = group)) +
scale_y_continuous(labels = scales::percent) +
scale_x_continuous(breaks = c(0:10)) +
labs(title = " To what extent are you satisfied with the current government's performance?",
x = "", y = "", fill = "") +
theme_minimal() +
theme(legend.text = element_text(size = 20),
plot.title = element_text(size = 32, hjust = 0),
axis.title = element_blank(),
axis.text = element_text(size = 20, colour = "black"),
axis.ticks.y = element_line(),
panel.border = element_rect(colour = "black", fill = NA),
panel.grid.minor = element_blank(),
panel.grid.major = element_blank())
Upvotes: 1