I want to move the position of the text describing the y-axis of a particular point in geom_text with R, so that the percentages are not mixed up and the graph is more readable. I only want to change the position of the text for the second point on the graph, and vjust changes the position of all the ordinates on the curve. I know my x-axis is not good but this is not my point here.
Here is my code:
library(tidyverse)
library(scales)
library(ggplot2)
ageC <- c("18-34","35", "35", "35","35","18-34","18-34","35","18-34","35")
sexe <- c("w","m", "m", "w", "w", "w", "m", "m", "m", "w")
sexuality <- c("no","yes", "no", "yes", "no", "no", "yes", "yes", "no", "yes")
df <- data.frame(ageC,sexe,sexuality)
# base with women
b_w <-
df %>%
select(ageC,sexe,sexuality) %>%
filter(sexe != "m") %>%
mutate(sexuality = factor(sexuality))
bb_w <-
b_w %>%
mutate(age_c = factor(ageC, labels = c("26", "35")) %>% as.character %>% as.numeric,
sexuality_c = as.numeric(sexuality=="yes")) %>%
group_by(age_c) %>%
summarise(sexuality_pct = mean(sexuality_c))
# base with men
b_m <-
df %>%
select(ageC,sexe,sexuality) %>%
filter(sexe != "w") %>%
mutate(sexuality = factor(sexuality))
bb_m <-
b_m %>%
mutate(age_c = factor(ageC, labels = c("26", "35")) %>% as.character %>% as.numeric,
sexuality_c = as.numeric(sexuality=="yes")) %>%
group_by(age_c) %>%
summarise(sexuality_pct = mean(sexuality_c))
ggplot() +
geom_point(data = bb_w, aes(x = age_c, y = sexuality_pct, fill = "w"),
color = "#6a51a3", size = 1.5) +
geom_text(data = bb_w, aes(x = age_c, y = sexuality_pct, label=percent(sexuality_pct, accuracy = .1)),
family = "Times New Roman",vjust = -0.4, size = 3.5) +
geom_point(data = bb_m, aes(x = age_c, y = sexuality_pct, fill = "m"),
color = "#41ae76", size = 1.5) +
geom_text(data = bb_m, aes(x = age_c, y = sexuality_pct, label=percent(sexuality_pct, accuracy = .1)),
family = "Times New Roman",vjust = +0.2, size = 3.5) +
geom_line(data = bb_w, aes(x = age_c, y = sexuality_pct), color = "#6a51a3", lwd = 1, alpha= 0.5) +
geom_line(data = bb_m, aes(x = age_c, y = sexuality_pct), color = "#41ae76", lwd = 1, alpha= 0.5 ) +
labs(x = "Age class", y = "Percentage") +
scale_y_continuous(labels = scales::percent) +
expand_limits(x = 15, y = 0) +
scale_x_continuous(limits = c(26,50), breaks = bb_w$age_c, labels = levels(b_w$age10)) +
theme(plot.title = element_text(hjust = 0.5), plot.subtitle = element_text(hjust = 0.5)) +
scale_fill_manual(name = NULL, values=c("w"="#6a51a3",
"m"="#41ae76" )) +
guides(fill = guide_legend(override.aes = list(shape=21, size = 5))) +
theme(text = element_text(family = "Times New Roman", size = 18))
You can streamline your prep and put vjust
into the aes()
for the geom_text
layer. (I presume you put the two categories into different tables so you could use separate layers with their own colors -- this can be done more concisely in most cases using an approach like scale_color_manual
below.) In this case I specify that the 2nd "w" point should be labelled underneath, while the other labels should be on top of their point.
df %>%
group_by(sexe, ageC) %>%
summarize(sexuality_pct = mean(sexuality == "yes"), .groups = "drop") %>%
ggplot(aes(ageC, sexuality_pct, color = sexe, group = sexe)) +
geom_point(size = 1.5) +
geom_line(show.legend = FALSE) +
geom_text(aes(label = percent(sexuality_pct, accuracy = .1),
vjust = ifelse(sexe == "w" & ageC == "35", 2, -1)), show.legend = FALSE) +
scale_color_manual(values = c("m" = "#41ae76", "w" = "#6a51a3"))
You can also use ggrepel
to un-overlap labels for you.
... +
ggrepel::geom_text_repel(aes(label = percent(sexuality_pct, accuracy = .1)),
show.legend = FALSE) +