为什么 geom_labels 向后?

Why are geom_labels backwards?

我正在使用出色的包 ggrepel() 将文本标签定位在带有一点抖动的条形图上。唯一的麻烦是它们出现的顺序相反。这是一些可重现的代码:

library(tidyverse)
require(scales)       # Used for adding percentages to bar charts
library(ggrepel)

# ingest some sample data
structure(list(Q52_bin = structure(c(3L, 2L, 2L, 2L, 2L, 2L, 
2L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 2L, 2L, 1L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 3L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 2L, 1L, 2L, 
2L, 1L, 3L, 2L, 3L, 3L, 1L), .Label = c("low", "medium", "high"
), class = "factor"), Q53_bin = structure(c(2L, 3L, 2L, 2L, 2L, 
2L, 2L, 3L, 2L, 3L, 2L, 1L, 2L, 2L, 1L, 2L, 3L, 2L, 2L, 1L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 2L, 2L, 3L, 1L, 
2L, 2L, 2L, 1L, 2L, 2L, 3L, 2L), .Label = c("low", "medium", 
"high"), class = "factor"), Q57_bin = structure(c(2L, 2L, 2L, 
2L, 2L, 2L, 2L, 1L, 1L, 1L, 3L, 2L, 2L, 2L, 2L, 2L, 3L, 2L, 1L, 
1L, 2L, 2L, 1L, 2L, 2L, 1L, 2L, 2L, 1L, 1L, 2L, 2L, 2L, 1L, 3L, 
3L, 1L, 2L, 2L, 2L, 2L, 1L, 3L, 2L, 2L), .Label = c("low", "medium", 
"high"), class = "factor"), Q4 = c(2, 3, 3, 5, 4, 3, 4, 5, 2, 
4, 2, 3, 5, 4, 3, 3, 5, 5, 4, 5, 3, 2, 4, 1, 5, 4, 4, 4, 4, 4, 
5, 3, 5, 1, 5, 5, 4, 5, 4, 1, 4, 2, 1, 5, 4)), row.names = c(NA, 
-45L), class = c("tbl_df", "tbl", "data.frame"))

df <- select(climate_experience_data, Q52_bin, Q53_bin, Q57_bin, Q4)
names(df) <- c("Q52_bin", "Q53_bin", "Q57_bin", "response")
facet_names <- c(`Q52_bin` = "Spirituality", `Q53_bin` = "Politics L/R", `Q57_bin` = "Religiosity", `low`="low", `medium`="medium", `high`="high")
facet_labeller <- function(variable,value){return(facet_names[value])}
q4_levels = c("Not at all", "A little", "Some", "A lot", "A great deal")
df$response <- factor(df$response, ordered = TRUE, levels = c("5", "4", "3", "2", "1"))
df$response <- fct_recode(df$response, "Not at all" = "1", "A little" = "2", "Some" = "3", "A lot" = "4", "A great deal" = "5")
caption <- "How much have you thought about climate change before today?"
df %>% 
  # we need to get the data including facet info in long format, so we use pivot_longer()
  pivot_longer(!response, names_to = "bin_name", values_to = "b") %>% 
  # add counts for plot below
  count(response, bin_name, b) %>%
  group_by(bin_name,b) %>%
  mutate(perc=paste0(round(n*100/sum(n),1),"%")) %>% 
  # run ggplot
  ggplot(aes(x = n, y = "", fill = response, label = perc)) +
  geom_col(position=position_fill(), aes(fill=response)) +
  coord_cartesian(clip = "off") +
  geom_label_repel(
    fill = "white", 
    size = 3,
    min.segment.length = 0,
    max.overlaps = Inf,
    position = position_fill()
    ) +
  scale_fill_brewer(palette="YlOrBr") +
  scale_x_continuous(labels = scales::percent_format(), expand = c(0.05, 0.05)) +
  facet_grid(vars(b), vars(bin_name), labeller=as_labeller(facet_names)) + 
  labs(caption = caption, x = "", y = "") + 
  guides(fill = guide_legend(title = NULL))
ggsave("figures/q4_faceted.png", width = 30, height = 10, units = "cm")

这是我得到的视觉效果:

那么标签反转是怎么回事?我担心剧情可能有些地方不准确!

问题是用于标签的分组变量与用于列的分组变量不同。要解决这个问题,您必须明确告诉 ggrepel 使用 group aes:

response 对标签进行分组
library(tidyverse)
library(ggrepel)

df_long <- df %>%
  pivot_longer(!response, names_to = "bin_name", values_to = "b") %>%
  count(response, bin_name, b) %>%
  group_by(bin_name, b) %>%
  mutate(perc = paste0(round(n * 100 / sum(n), 1), "%"))

ggplot(df_long, aes(x = n, y = "")) +
  geom_col(position = position_fill(), aes(fill = response)) +
  coord_cartesian(clip = "off") +
  geom_label_repel(
    aes(group = response, label = perc),
    fill = "white",
    size = 3,
    min.segment.length = 0,
    max.overlaps = Inf,
    position = position_fill()
  ) +
  scale_fill_brewer(palette = "YlOrBr") +
  scale_x_continuous(labels = scales::percent_format(), expand = c(0.05, 0.05)) +
  facet_grid(vars(b), vars(bin_name), labeller = as_labeller(facet_names)) +
  labs(caption = caption, x = "", y = "") +
  guides(fill = guide_legend(title = NULL))