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

在ggplot2柱状图Y轴添加百分号的报错问题及适配问询

在ggplot2柱状图Y轴添加百分号的问题解决

问题详情

用户需要在ggplot2绘制的柱状图Y轴上显示百分号,尝试修改代码后出现报错,且多分类X变量场景下代码失效,仅二分类X变量时可运行。

数据示例

# 数据片段
structure(list(socio_egotropic = c("egotropic", "egotropic", 
"egotropic", "sociotropic", "sociotropic"), active = c("both", 
"post-treatment", "pre-treatment", "both", "post-treatment"), 
    n = c(155L, 55L, 225L, 236L, 32L), percentage = c(35.632183908046, 
    12.6436781609195, 51.7241379310345, 37.4009508716323, 5.07131537242472
    )), class = c("grouped_df", "tbl_df", "tbl", "data.frame"
), row.names = c(NA, -5L), groups = structure(list(socio_egotropic = c("egotropic", 
"sociotropic"), .rows = structure(list(1:3, 4:5), ptype = integer(0), class = c("vctrs_list_of", 
"vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -2L), .drop = TRUE))

当前绘图代码与效果

ggplot(user_patterns, aes(active, percentage, fill = socio_egotropic)) + 
  geom_bar(stat = 'identity', position = 'dodge') +
  theme_bw()                          

当前无百分号的柱状图

尝试修改后的代码及报错

修改代码试图添加百分号和调整Y轴刻度,但触发警告:

ggplot(user_patterns, aes(active, percentage, fill = socio_egotropic)) + 
  geom_bar(stat = 'identity', position = 'dodge') +
  scale_y_continuous(labels = percent_format(accuracy = 1)) +
  scale_y_continuous(breaks = seq(0, .85, .10),
                    labels = scales::percent,
                    limits = c(0, .85)) + 
  scale_x_discrete(limits = c("both", "post-treatment", "pre-treatment")) +
  theme_bw()

报错信息:

Scale for 'y' is already present. Adding another scale for 'y', which will replace the existing scale.
Scale for 'fill' is already present. Adding another scale for 'fill', which will replace the existing scale.

补充场景:二分类X变量可运行

当X变量为二分类时,代码看似正常运行(实际写法仍不规范),代码及效果如下:

ggplot(data = user_patterns, aes(x = treatment_implementation, fill = socio_egotropic, y = socio_egotropic_percentage)) + 
  geom_bar(stat = "identity", position=position_dodge()) + 
  scale_fill_grey() +
  xlab("Sociotropic vs. Egotropic experiences relative to implementation") + 
  ylab("Sociotropic vs. Egotropic share by period") + 
  theme(text=element_text(size=20)) + 
  scale_fill_manual(values = c("sociotropic" = "purple",
                               "egotropic" = "blue")) +
  theme(plot.title = element_text(size = 18, face = "bold")) +
  scale_y_continuous(labels = percent_format(accuracy = 1)) +
  scale_y_continuous(breaks = seq(0, .85, .10),
                     labels = scales::percent,
                     limits = c(0, .85)) + 
  scale_x_discrete(limits = c("pre", "post")) +
  theme_bw()

二分类X变量的柱状图


问题原因与解决方案

核心问题分析

  1. 重复设置Y轴刻度:你调用了两次scale_y_continuous,ggplot2不允许对同一轴重复设置刻度,后一次会覆盖前一次并触发警告。
  2. 数值与百分比转换不匹配:你的percentage列是原始百分比数值(如35.63代表35.63%),但scales::percent()默认将0-1之间的比例转换为百分比(如0.35→35%),直接使用会导致数值被放大100倍(35.63→3563%)。

针对多分类X变量的正确代码

方法1:直接给数值添加百分号

适合原始数据是百分比数值的场景:

library(ggplot2)

ggplot(user_patterns, aes(active, percentage, fill = socio_egotropic)) + 
  geom_bar(stat = 'identity', position = 'dodge') +
  # 合并Y轴所有设置:断点、标签、范围
  scale_y_continuous(
    breaks = seq(0, 85, 10),  # 匹配数据范围设置刻度断点
    labels = function(x) paste0(x, "%"),  # 直接给数值追加百分号
    limits = c(0, 85)
  ) +
  scale_x_discrete(limits = c("both", "post-treatment", "pre-treatment")) +
  theme_bw()

方法2:使用scales::percent()转换

先将原始百分比数值除以100转为0-1的比例,再用scales::percent()生成标签:

library(ggplot2)
library(scales)

ggplot(user_patterns, aes(active, percentage/100, fill = socio_egotropic)) + 
  geom_bar(stat = 'identity', position = 'dodge') +
  scale_y_continuous(
    breaks = seq(0, 0.85, 0.1),
    labels = percent(accuracy = 1),  # 保留1位小数的百分号标签
    limits = c(0, 0.85)
  ) +
  scale_x_discrete(limits = c("both", "post-treatment", "pre-treatment")) +
  ylab("百分比") +  # 自定义Y轴标签
  theme_bw()

二分类场景的规范写法

二分类场景虽然能运行,但重复调用scale_y_continuous是不规范的,应合并为一次调用:

ggplot(data = user_patterns, aes(x = treatment_implementation, fill = socio_egotropic, y = socio_egotropic_percentage)) + 
  geom_bar(stat = "identity", position=position_dodge()) + 
  scale_fill_manual(values = c("sociotropic" = "purple", "egotropic" = "blue")) +
  xlab("Sociotropic vs. Egotropic experiences relative to implementation") + 
  ylab("Sociotropic vs. Egotropic share by period") + 
  theme(text=element_text(size=20),
        plot.title = element_text(size = 18, face = "bold")) +
  # 合并Y轴设置
  scale_y_continuous(
    breaks = seq(0, 0.85, 0.1),
    labels = percent(accuracy = 1),
    limits = c(0, 0.85)
  ) +
  scale_x_discrete(limits = c("pre", "post")) +
  theme_bw()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 06:20:53