R语言循环多列绘制时间序列图并保存时出现非数值参数错误的解决方法
解决ggplot批量绘制多列时间序列图的错误问题
我明白你遇到的困扰了——单个变量绘图时一切正常,但用for循环批量处理v1、v2这类列时,突然弹出Error in colName/100 : non-numeric argument to binary operator的错误。这是因为你直接在ggplot的aes()里用字符串类型的列名colName,ggplot没法自动把它映射成数据框里对应的数值列,而且colName/100本质上是在对字符串做除法,自然会触发非数值参数的错误。
下面是修正后的完整代码,我会标注关键修改点:
library(ggrepel) library(ggplot2) library(scales) # 数据预处理(和你原代码保持一致) df$date <- as.Date(df$date, format="%Y-%m-%d") df$year <- format(df$date, "%Y") df$month <- as.numeric(format(df$date, "%m")) # 自定义ggsave函数(保留你的设置) ggsave <- function(...) { ggplot2::ggsave(...) ; invisible() } # 批量绘图循环 colNames <- names(df)[2:3] # 提取需要绘制的列名(v1、v2) for (colName in colNames){ ggplot(df, aes(x = month, y = .data[[colName]], color = year, linetype = year, shape = year)) + geom_point() + geom_line() + ylab(colName) + xlab('月份') + # 可选:给x轴加清晰标签,也可以保持空字符串 scale_x_continuous(breaks = 1:12, labels = 1:12) + # 用1-12替代重复的df$month,逻辑更严谨 scale_y_continuous(labels = percent_format(accuracy = 0.1)) + # 用scales包内置函数简化百分比格式 geom_text_repel(aes(label= percent(.data[[colName]]/100, accuracy = 0.1)), size=4, show.legend = FALSE) + # 替换旧参数show_guide为show.legend ggsave(paste0('./', colName, '.png'), width = 10, height = 6) # paste0比paste更简洁的字符串拼接 }
关键修改说明:
- 动态引用列名:用
.data[[colName]]替代直接写colName,这是ggplot官方推荐的动态列引用方式,能明确告诉ggplot“从当前数据框中取名为colName的数值列”,而不是把colName当成字符串处理; - 简化百分比格式:用
scales::percent_format()替代自定义的label函数,代码更简洁且符合规范; - 优化x轴刻度:把
scale_x_continuous的breaks设置为1:12,避免原代码中df$month带来的重复刻度值,逻辑更严谨; - 更新参数:将
show_guide = F替换为show.legend = FALSE,因为show_guide是ggplot旧版本的参数,新版本已用show.legend替代,兼容性更好。
内容的提问来源于stack exchange,提问作者ah bon
相关产品推荐
相关产品推荐

