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

基于参考方案修复R语言ggplot绘图宽度问题的代码排查求助

问题排查求助

我之前的问题被关闭并指向一个已解答的帖子,该帖子的方案对我有帮助,但由于知识缺口,我无法将其应用到自己的R代码中。我的原代码用于根据AMETIALAGRUPP列的不同分组生成对应数量的条形图,尝试整合参考的fixed_bars函数但未能成功运行,现求助排查代码问题。

原代码

DATA <- read_xlsx("T:/Data/TEST_DATA.xlsx")

make_plot <- function(ametialagrupp){
  
  DATA <- DATA %>%
    filter(AMETIALAGRUPP == ametialagrupp,
           HARIDUSTASE_YLD == "Korg") %>%
    mutate(OKR_N = fct_reorder(OKR_N, INIMEST)) %>%
    slice_head(n=5)
  
  
p <-  ggplot(DATA ,aes(y=OKR_N, x=INIMEST, fill=HARIDUSVOTI))+
    geom_bar(stat = 'identity',width = 0.8)+
    scale_fill_manual(values = c("#0071ce","#d30031"),
                      name=" ",
                      labels=c("Erialane","Mitteerialane"))+
    theme_minimal()+
    xlab("Inimest")+
    theme(legend.position = "bottom",
          axis.title.y=element_blank(),
          panel.grid.major.y = element_blank())

  ggsave(p, file=paste("AG_",ametialagrupp,"_4" , ".png", sep=""),path="T:/DATA/AG", height=4, width=6, bg="white", scale=1.2)
}

make_plot("Group_1")

for(i in unique( DATA$AMETIALAGRUPP)) make_plot(i)

参考代码(附疑问)

library(ggplot2)
library(dplyr)

fixed_bars <- function(data, var, ncols = 6) { # var是什么?我需要修改它吗?
  ncols   <- ncols + 2 # ncols=6是怎么来的?为什么要+2?
  data    <- mutate(data, {{var}} := as.factor({{var}}))
  levs    <- length(levels(pull(data, {{var}})))
  extra   <- ncols - levs
  x_range <- range(as.numeric(pull(data, {{var}}))) + c(-0.5, 0.5) * extra 

# 因为我不太懂ggplot的机制,所以这段代码我看不懂

  ggplot(data, aes(x = {{var}})) +
    geom_bar() +
    coord_cartesian(xlim = x_range)
}

尝试整合的代码

DATA <- read_xlsx("T:/Data/TEST_DATA.xlsx")

fixed_bars <- function(DATA
, var, ncols = 6) {
  ncols   <- ncols + 2
  data    <- mutate(AMETIALAGRUPID, {{var}} := as.factor({{var}}))
  levs    <- length(levels(pull(AMETIALAGRUPID, {{var}})))
  extra   <- ncols - levs
  x_range <- range(as.numeric(pull(AMETIALAGRUPID, {{var}}))) + c(-0.5, 0.5) * extra
  
  ggplot(AMETIALAGRUPID, aes(y = {{var}} x=INIMEST, fill=HARIDUSVOTI)) +
    geom_bar(stat = 'identity')+
    scale_fill_manual(values = c("#0071ce","#d30031"),
                      name=" ",
                      labels=c("Erialane","Mitteerialane"))+
    theme_minimal()+
    xlab("Inimest")+
    theme(legend.position = "bottom",
          axis.title.y=element_blank(),
          panel.grid.major.y = element_blank())+
    coord_cartesian(ylim = x_range)
}

mpg %>%
  fixed_bars(OKR_N)
 

make_plot <- function(ametialagrupp){
  
  DATA <- DATA %>%
    filter(AMETIALAGRUPP == ametialagrupp,
           HARIDUSTASE_YLD == "Korg") %>%
    mutate(OKR_N = fct_reorder(OKR_N, INIMEST)) %>%
    slice_head(n=5)
  
  
p <-  DATA %>%
     fixed_bars(OKR_N)

  ggsave(p, file=paste("AG_",ametialagrupp,"_4" , ".png", sep=""),path="T:/DATA/AG", height=4, width=6, bg="white", scale=1.2)
}

make_plot("Group_1")

for(i in unique( DATA$AMETIALAGRUPP)) make_plot(i)

问题分析与修正代码

核心问题点

  • 数据引用错误:fixed_bars函数里错误使用了未定义的AMETIALAGRUPID,应该用函数参数传入的数据集。
  • ggplot语法错误:aes(y = {{var}} x=INIMEST)缺少逗号分隔参数,正确写法是aes(y = {{var}}, x=INIMEST, fill=HARIDUSVOTI)。
  • 坐标轴范围适配错误:原参考代码针对纵向条形图的x轴,你的图是横向条形图(y轴为分类变量),需要调整ylim的计算逻辑。
  • 冗余测试代码:mpg %>% fixed_bars(OKR_N)与你的业务数据无关,应该删除。
  • 全局变量覆盖风险:函数内修改全局DATA变量,容易引发意外错误,改用局部变量存储过滤后的数据。

修正后的完整代码

library(ggplot2)
library(dplyr)
library(readxl)
library(forcats)

# 适配横向条形图的fixed_bars函数:固定分类轴(y轴)宽度
fixed_bars <- function(data, var, target_bars = 5) { 
  # target_bars对应slice_head取的5条数据,确保所有图表y轴宽度一致
  data <- mutate(data, {{var}} := as.factor({{var}}))
  current_levs <- length(levels(pull(data, {{var}})))
  extra_space <- target_bars - current_levs
  # 计算y轴范围:分类变量转数值后,两端补充空白空间
  y_range <- range(as.numeric(pull(data, {{var}}))) + c(-0.5, 0.5) * extra_space
  
  ggplot(data, aes(y = {{var}}, x = INIMEST, fill = HARIDUSVOTI)) +
    geom_bar(stat = 'identity', width = 0.8) +
    scale_fill_manual(values = c("#0071ce","#d30031"),
                      name = " ",
                      labels = c("Erialane","Mitteerialane")) +
    theme_minimal() +
    xlab("Inimest") +
    theme(legend.position = "bottom",
          axis.title.y = element_blank(),
          panel.grid.major.y = element_blank()) +
    coord_cartesian(ylim = y_range)
}

make_plot <- function(ametialagrupp){
  # 用局部变量存储过滤后的数据,避免修改全局变量
  filtered_data <- DATA %>%
    filter(AMETIALAGRUPP == ametialagrupp,
           HARIDUSTASE_YLD == "Korg") %>%
    mutate(OKR_N = fct_reorder(OKR_N, INIMEST)) %>%
    slice_head(n=5)
  
  p <- filtered_data %>% fixed_bars(OKR_N)
  
  ggsave(p, file=paste("AG_",ametialagrupp,"_4" , ".png", sep=""),
         path="T:/DATA/AG", height=4, width=6, bg="white", scale=1.2)
}

# 读取数据
DATA <- read_xlsx("T:/Data/TEST_DATA.xlsx")

# 单分组测试
make_plot("Group_1")

# 遍历所有分组生成图表
for(i in unique(DATA$AMETIALAGRUPP)) make_plot(i)

参考代码疑问解答

  1. var参数:是你要固定宽度的分类变量,在你的场景里就是OKR_N,调用函数时传入即可,不需要修改函数内部的var。
  2. ncols = 6与+2:原参考代码是针对纵向条形图(x轴为分类),设置目标列数为6,+2是为了给两端留空白空间。你的场景是横向条形图,我们改成target_bars = 5,对应你取的前5条数据,更贴合需求。
  3. ggplot逻辑:核心是把分类变量转成数值,计算需要补充的空白空间,再通过coord_cartesian固定坐标轴范围,让所有分组的图表分类轴宽度一致,方便对比。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 09:40:31