You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

scale_x_discrete为何重复数据?ggplot2轴标签异常问题

ggplot2中scale_x_discrete的x轴标签出现循环复用问题

问题描述

构建数据并添加排序用的gruppen_id后,绘制条形图时整体显示正常,但通过scale_x_discrete设置的x轴标签中,“n (total)”的值出现循环复用(recycle)错误。相关代码如下:

数据构建与排序代码

library(tidyverse)
library(ggplot2)
library(ggtext)

df <- structure(
  list(
    variable = c(
      "var1", "var1", "var1", "var2", "var2", "var2",
      "var3", "var3", "var3", "var4", "var4", "var4"
    ),
    gruppe = structure(
      c(1L, 7L, 16L, 1L, 7L, 16L, 1L, 7L, 16L, 1L, 7L, 16L),
      levels = c(
        "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF",
        "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLL",
        "MMMM", "NNNN", "OOOO", "PPPP GGGG"
      ),
      class = "factor"
    ),
    auspraegung = rep("lorem ipsum", 12),
    n = c(148L, 32L, 89L, 135L, 31L, 93L, 123L, 28L, 76L, 115L, 26L, 67L),
    prozent = c(88.1, 84.2, 85, 81.3, 81.6, 89, 74.1, 73.7, 72, 69.7, 68.4, 65),
    gruppen_variablen_summe = c(168L, 38L, 105L, 166L, 38L, 105L, 166L, 38L, 105L, 165L, 38L, 103L),
    auspr_n = c(
      "88.1% \nn = 148", "84.2% \nn = 32", "85% \nn = 89",
      "81.3% \nn = 135", "81.6% \nn = 31", "89% \nn = 93",
      "74.1% \nn = 123", "73.7% \nn = 28", "72% \nn = 76",
      "69.7% \nn = 115", "68.4% \nn = 26", "65% \nn = 67"
    ),
    gruppe_n = c(
      "AAAA \nn = 168", "GGGG \nn = 38", "PPPP GGGG \nn = 105",
      "AAAA \nn = 166", "GGGG \nn = 38", "PPPP GGGG \nn = 105",
      "AAAA \nn = 166", "GGGG \nn = 38", "PPPP GGGG \nn = 105",
      "AAAA \nn = 165", "GGGG \nn = 38", "PPPP GGGG \nn = 103"
    )
  ),
  class = c("grouped_df", "tbl_df", "tbl", "data.frame"),
  row.names = c(NA,-12L),
  groups = structure(
    list(
      variable = c(
        "var1", "var1", "var1", "var2", "var2", "var2",
        "var3", "var3", "var3", "var4", "var4", "var4"
      ),
      gruppe = structure(
        c(1L,7L,16L,1L,7L,16L,1L,7L,16L,1L,7L,16L),
        levels = c(
          "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF",
          "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLL",
          "MMMM", "NNNN", "OOOO", "PPPP GGGG"
        ),
        class = "factor"
      ),
      .rows = structure(
        list(1L,2L,3L,4L,5L,6L,7L,8L,9L,10L,11L,12L),
        ptype = integer(0),
        class = c("vctrs_list_of","vctrs_vctr","list")
      )
    ),
    class = c("tbl_df","tbl","data.frame"),
    row.names = c(NA,-12L),
    .drop = TRUE
  )
)

varlabels <- c(
  "var1" = "Text var 1",
  "var2" = "Text var 2",
  "var3" = "Text var 3",
  "var4" = "Text var 4"
)

# 添加分组ID用于排序
df$gruppen_id <- rep(c(2,1,3), times = 4)

原因分析

出现循环复用的核心原因是传入scale_x_discrete(labels = ...)的标签向量长度,与x轴实际的离散刻度数量不匹配:

  • 你的x轴对应的离散变量(gruppe)只有3个唯一级别:AAAA、GGGG、PPPP GGGG。
  • 如果错误地传入长度为12的向量(比如直接用df$gruppe_n),R会触发向量循环机制——重复短向量直到匹配长向量的长度,导致标签被循环复用,显示错误的“n (total)”值。

解决方法

1. 生成匹配长度的标签向量

先提取每个分组对应的唯一总样本量,生成与x轴刻度数量一致的标签:

# 按排序ID提取每个分组的唯一标签
group_labels <- df %>%
  distinct(gruppe, gruppen_variablen_summe, gruppen_id) %>%
  arrange(gruppen_id) %>% # 按指定顺序排序
  mutate(label = paste0(gruppe, "\nn (total) = ", gruppen_variablen_summe)) %>%
  pull(label)

2. 在绘图中使用正确的标签

在scale_x_discrete中传入生成的标签向量,同时用reorder确保条形按指定顺序排列:

ggplot(df, aes(x = reorder(gruppe, gruppen_id), y = prozent, fill = gruppe)) +
  geom_col(position = "dodge") + # 根据需求调整位置
  scale_x_discrete(labels = group_labels) +
  facet_wrap(~variable, labeller = labeller(variable = varlabels)) + # 可选:添加变量标签
  labs(x = "分组", y = "百分比") +
  theme_minimal()

这样就能保证每个x轴刻度对应正确的“n (total)”值,不会出现循环复用的问题。

内容的提问来源于stack exchange,提问作者Dierforth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 23:40:34