基于参考方案修复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)
参考代码疑问解答
var参数:是你要固定宽度的分类变量,在你的场景里就是OKR_N,调用函数时传入即可,不需要修改函数内部的var。ncols = 6与+2:原参考代码是针对纵向条形图(x轴为分类),设置目标列数为6,+2是为了给两端留空白空间。你的场景是横向条形图,我们改成target_bars = 5,对应你取的前5条数据,更贴合需求。- ggplot逻辑:核心是把分类变量转成数值,计算需要补充的空白空间,再通过
coord_cartesian固定坐标轴范围,让所有分组的图表分类轴宽度一致,方便对比。
内容的提问来源于stack exchange,提问作者Picataro
相关产品推荐
相关产品推荐

