基于Type与Sub_type配对批量绘制多列年度数据趋势图问题
R语言批量分组趋势图问题解决
需求说明
需使用R语言实现批量绘图:以year为X轴,遍历所有data_column_*列,同时按type与对应的sub_type(仅同type内的sub_type配对,不同type的同名sub_type不混合绘图)分组生成趋势图,例如Brand&Ambient、Brand&Food等组合。
示例数据
structure(list(year = c(2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2018, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2019, 2020, 2020, 2020), type = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 3L,3L, 3L, 1L, 1L, 1L, 1L, 2L, 3L, 3L, 3L, 1L, 1L, 1L), levels = c("Brand","Shop", "Retail"), class = "factor"), sub_type = structure(c(1L, 2L, 3L, 6L, 3L, 6L, 4L, 6L, 7L, 1L, 2L, 3L, 6L, 5L, 4L, 6L, 7L, 1L, 2L, 3L), levels = c("Ambient", "Food", "Drink", "Grocery", "non-grocery", "non-drink","Food"), class = "factor"), data_column_1 = c(14, 11, 42, 68, 1, 0, 30, 20, 75, 23, 16, 0, 15, 0, 46, 26, 42, 19, 56, 0), data_column_2 = c(NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), data_column_3 = c(198, 527, 0, 224, 176, 0, 322, 2, 564, 973, 506, 0, 569, 0, 452, 422, 456, 720, 255, 0), data_column_4 = c(NA_real_,NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 56, NA_real_, NA_real_, 62,NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), data_column_5 = c(1600, 206, 150,36, 0, 0, 702, 263, 0, 1124, 215, 68,718, 0, 1938, 584, 0, 652, 181,67)), class = c("grouped_df", "tbl_df", "tbl", "data.frame"), row.names = c(NA, -20L), groups = structure(list(year = c(2018,2018, 2018, 2019, 2019, 2019, 2020), sigtype = structure(c(1L,2L, 3L, 1L, 2L, 3L, 1L), levels = c("Brand", "Shop","Retail"), class = "factor"), .rows = structure(list(1:4, 5:6,7:9, 10:13, 14L, 15:17, 18:20), ptype = integer(0), class = c("vctrs_list_of","vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -7L), .drop = TRUE))
现有尝试代码
other.unknown.columns <- colnames(df) other.unknown.columns <- other.unknown.columns[-c(1,2,3)] # remove year, type, sub_type setwd("my/filepath") df$type <- factor(df$sigtype) df$subtype <- factor(df3$sub_type) type.levels <- levels(df$type) sub_type.levels <- levels(df$sub_type) for (i in type.levels) { workingData <- subset(df, type == i) # this was an attempt to only have one type present, therefore to not iterate through unnecessary sub_types for (j in sub_type.levels) { for(k in other.unknown.columns){ g <- ggplot(workingData, aes(x=year, y=.data[[k]])) + geom_line() + geom_point() + ggtitle(heading) print(g) dev.off() filename<-paste(i, "_", j, "_", k, ".png", sep="") png(filename = filename, width=720) heading<-paste(i," sub_type ",j," - ", k) } } } dev.list() dev.off()
遇到的问题
- 生成了所有
type与sub_type的组合,而非仅同type内存在的sub_type配对; - 绘图数据对应错误,出现单年度多个数据点的问题;
dev.off使用易出现异常。
解决方案
核心修正点
- 仅遍历当前type下存在的sub_type:不再使用全局的sub_type水平,而是对每个type的子集提取实际存在的sub_type值,避免生成无效组合。
- 精准筛选分组数据:每个绘图数据集同时匹配
type和sub_type,确保每个year对应唯一数据点。 - 规范图形设备流程:先打开png设备,再绘图打印,最后关闭设备,避免顺序颠倒导致的异常。
修正后的代码
# 加载依赖包 library(ggplot2) # 设置输出路径 setwd("my/filepath") # 自动匹配所有data_column开头的列 data_cols <- colnames(df)[grepl("data_column_", colnames(df))] # 获取所有唯一的type值 type_list <- unique(df$type) # 遍历每个type for (i in type_list) { # 获取当前type下实际存在的sub_type(去重) sub_type_list <- unique(df$sub_type[df$type == i]) # 遍历当前type下的每个sub_type for (j in sub_type_list) { # 筛选当前type+sub_type的目标数据集 plot_data <- df[df$type == i & df$sub_type == j, ] # 遍历每个数据列 for (k in data_cols) { # 跳过全为NA的列,避免生成空图 if (all(is.na(plot_data[[k]]))) next # 定义文件名和标题 filename <- paste0(i, "_", j, "_", k, ".png") heading <- paste(i, "sub_type", j, "-", k) # 打开图形设备 png(filename = filename, width = 720) # 绘制趋势图 g <- ggplot(plot_data, aes(x = year, y = .data[[k]])) + geom_line() + geom_point() + ggtitle(heading) + theme_minimal() # 可选:美化图形主题 print(g) # 关闭图形设备 dev.off() } } }
额外优化
- 自动识别
data_column_开头的列,无需手动排除列,适配数据结构变化; - 增加全NA列判断,跳过无有效数据的绘图任务;
- 修正原代码中的变量名错误(
df3→df、sigtype→type); - 加入
theme_minimal()美化图形,可根据需求替换其他主题。
内容的提问来源于stack exchange,提问作者MintySusan
相关产品推荐
相关产品推荐

