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

使用ggplot绘制风玫瑰图时遇「至少一个图层需包含所有分面变量」错误

解决分面风玫瑰图报错问题

报错原因

原plot.windrose函数生成的绘图数据是基于整个数据集的汇总结果,没有保留班次(或日期)这类分面变量,所以添加facet_wrap时,ggplot找不到对应的变量,导致报错。

解决方案

下面提供两种可行的解决方法:


方法一:分组生成单图后组合

先按班次拆分数据集,对每个班次单独生成风玫瑰图,再用patchwork包组合成多面板图。

  1. 准备环境与数据
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))
  1. 拆分数据并生成单图
# 按班次拆分数据集
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)))
})
  1. 组合所有图形
combined_plot <- wrap_plots(plot_list, ncol = 2)
print(combined_plot)

方法二:修改plot.windrose函数支持分面

直接修改原函数,让它接受分组参数,在数据汇总时保留分组信息,直接生成分面图。

  1. 修改后的函数代码
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)
}
  1. 直接调用生成分面图
# 生成按班次分面的风玫瑰图
facet_windrose <- plot.windrose_facet(data = df_0, spd = "BSP", dir = "TWD", group = "watch_asfactor")
print(facet_windrose)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 05:13:12