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

为数据框选中列生成带百分比柱状图时的异常问题排查

解决ggplot2生成百分比柱状图的异常问题

问题场景

你有如下示例数据:

library(dplyr)
library(tidyr)

# example data frame
df <- data.frame(
  col1 = c("A;B;C", "A;B", "B;C", "A;C", "B", "A;B;C;D"),
  col2 = c("X;Y;Z", "X;Y", "Y;Z", "X;Z", "Z", "W;X;Y;Z"),
  col3 = c("1;2", "1", "2;3", "3", "4;5;6", "7"),
  col4 = c(1, 2, 3, 4, 5, 6),
  col5 = c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE)
)

# select columns to separate
selected_cols <- c("col1", "col2", "col3", "col4", "col5")

原本生成计数柱状图的代码是:

library(ggplot2)
library(tidyr)

lapply(c("col1", "col2"), function(col) {
  separate_rows(df, all_of(col), sep = ";") |>
    ggplot(aes(.data[[col]])) +
    geom_bar(aes(fill = .data[[col]]))
})

你修改为百分比柱状图的代码后出现异常,修改后的代码:

lapply(c("col1", "col2"), function(col) {
  separate_rows(df, all_of(col), sep = ";") |>
    ggplot(aes(.data[[col]])) +
    geom_bar(aes(fill = .data[[col]])) +
    stat_count(aes(y = (..count..)/sum(..count..)), position = "identity") +
    scale_y_continuous(labels = scales::percent)
})

错误原因

你的代码同时调用了geom_bar()和stat_count(),而geom_bar()默认就是使用stat_count()来计算并绘制计数柱状图的。这相当于在同一个图表上叠加了两层柱子:一层是原始计数高度的柱子,另一层是百分比高度的柱子,两者叠加导致图形异常。

修正方案

方案1:直接修改geom_bar的y轴映射

无需额外调用stat_count(),直接在geom_bar()的aes里定义百分比计算逻辑:

library(ggplot2)
library(tidyr)
library(scales) # 加载scales包以使用百分比标签

lapply(c("col1", "col2"), function(col) {
  separate_rows(df, all_of(col), sep = ";") |>
    ggplot(aes(.data[[col]])) +
    geom_bar(aes(y = (..count..)/sum(..count..), fill = .data[[col]])) +
    scale_y_continuous(labels = percent)
})

方案2:先预处理数据计算百分比(推荐)

这种方式更直观,提前在数据层面计算好百分比,避免依赖ggplot内部的..count..变量,也更容易排查数据问题:

library(ggplot2)
library(tidyr)
library(dplyr)
library(scales)

lapply(c("col1", "col2"), function(col) {
  separate_rows(df, all_of(col), sep = ";") |>
    # 统计每个类别出现的次数
    count(.data[[col]]) |>
    # 计算每个类别占总数的百分比
    mutate(pct = n / sum(n)) |>
    ggplot(aes(x = .data[[col]], y = pct, fill = .data[[col]])) +
    geom_col() + # 使用geom_col而非geom_bar,因为y轴是已计算好的值
    scale_y_continuous(labels = percent)
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 21:47:07