使用ggplot绘制风玫瑰图时遇「至少一个图层需包含所有分面变量」错误
解决分面风玫瑰图报错问题
报错原因
原plot.windrose函数生成的绘图数据是基于整个数据集的汇总结果,没有保留班次(或日期)这类分面变量,所以添加facet_wrap时,ggplot找不到对应的变量,导致报错。
解决方案
下面提供两种可行的解决方法:
方法一:分组生成单图后组合
先按班次拆分数据集,对每个班次单独生成风玫瑰图,再用patchwork包组合成多面板图。
- 准备环境与数据
install.packages("patchwork") library(patchwork) library(dplyr) # 你的示例数据 df_0 <- data.frame(UTC = c(45117.171132,45117.17371,45117.358592,45117.360963,45117.376829,45117.393799,45117.401636,45117.465761,45117.483411,45117.488394), BSP = c(7.343,8.033,6.816,8.197,11.814,8.724,6.997,10.269,10.614,10.796), TWD = c(75.5,55.5,37.6,39.9,27.7,136.1,122,33.7,46.8,45.1), TWS = c(16.41,14.45,16.5,18.68,17.33,17.79,17.93,17.97,22.36,18.43), watch_lbl_adj = c("K","K","A","A","B","B","B","C","C","C")) df_0 <- df_0 %>% mutate(watch_asfactor = factor(watch_lbl_adj))
- 拆分数据并生成单图
# 按班次拆分数据集 df_list <- split(df_0, df_0$watch_asfactor) # 对每个班次生成风玫瑰图 plot_list <- lapply(df_list, function(sub_df) { plot.windrose(data = sub_df, spd = "BSP", dir = "TWD") + ggtitle(paste("班次:", unique(sub_df$watch_asfactor))) })
- 组合所有图形
combined_plot <- wrap_plots(plot_list, ncol = 2) print(combined_plot)
方法二:修改plot.windrose函数支持分面
直接修改原函数,让它接受分组参数,在数据汇总时保留分组信息,直接生成分面图。
- 修改后的函数代码
plot.windrose_facet <- function(data, spd, dir, group = NULL, spdres = 2, dirres = 30, spdmin = 0, spdmax = NA, spdseq = NA, palette = "YlGnBu", countmax = NA){ # 提取风速、风向数据 data$spd <- data[[spd]] data$dir <- data[[dir]] # 处理分组变量 if (!is.null(group)) { data$group <- factor(data[[group]]) } # 划分风速区间 if (is.na(spdmax)) spdmax <- max(data$spd, na.rm = TRUE) if (is.na(spdseq)) spdseq <- seq(spdmin, spdmax, spdres) spd_bins <- cut(data$spd, breaks = spdseq, include.lowest = TRUE) spd_labels <- paste0(spdseq[-length(spdseq)], "-", spdseq[-1]) # 划分风向区间 dir_bins <- cut(data$dir, breaks = seq(0, 360, dirres), include.lowest = TRUE) dir_labels <- paste0(seq(0, 360-dirres, dirres), "-", seq(dirres, 360, dirres)) # 生成交叉统计表(包含分组信息) if (!is.null(group)) { wind_table <- table(data$group, spd_bins, dir_bins) wind_data <- as.data.frame(wind_table) names(wind_data) <- c("group", "spd", "dir", "count") } else { wind_table <- table(spd_bins, dir_bins) wind_data <- as.data.frame(wind_table) names(wind_data) <- c("spd", "dir", "count") } # 整理标签与角度数据 wind_data$spd <- factor(wind_data$spd, levels = spd_labels, labels = spd_labels) wind_data$dir <- factor(wind_data$dir, levels = dir_labels, labels = dir_labels) wind_data$dir_angle <- as.numeric(substr(wind_data$dir, 1, 3)) + dirres/2 # 设置频次上限 if (is.na(countmax)) countmax <- max(wind_data$count, na.rm = TRUE) # 绘制基础风玫瑰图 p <- ggplot(wind_data, aes(x = dir_angle, y = count, fill = spd)) + geom_bar(stat = "identity", width = dirres) + coord_polar(start = -dirres/2*pi/180) + scale_x_continuous(breaks = seq(0, 360-dirres, dirres), labels = seq(0, 360-dirres, dirres)) + scale_fill_brewer(palette = palette) + theme_bw() + labs(x = "风向(°)", y = "频次", fill = "船速(knots)") + theme(axis.text.y = element_blank(), axis.ticks.y = element_blank()) # 添加分面(如果有分组变量) if (!is.null(group)) { p <- p + facet_wrap(~group, ncol = 2) } return(p) }
- 直接调用生成分面图
# 生成按班次分面的风玫瑰图 facet_windrose <- plot.windrose_facet(data = df_0, spd = "BSP", dir = "TWD", group = "watch_asfactor") print(facet_windrose)
内容的提问来源于stack exchange,提问作者inneljpn
相关产品推荐
相关产品推荐

