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

如何用geom_quiver可视化风数据:简化箭头数量及解决箭头大小疑问

嘿,这两个问题我用geom_quiver做气象可视化的时候也踩过坑,给你详细说说解决方案:

问题1:减少箭头数量,用区域平均的大箭头代替密集小箭头

要只放3-5个代表区域平均的大箭头,核心思路是先把你的风速风向数据按五大湖的区域分组,计算每组的平均经纬度、平均风速、平均风向,再用汇总后的结果画箭头。这里有两种实用方法:

方法1:手动划分区域(适合对五大湖熟悉的情况)

你可以根据五大湖的地理范围,把经纬度切成3-5个区间,或者直接按湖划分(比如苏必利尔湖、密歇根湖等各一组),然后用dplyr做分组汇总:

library(dplyr)
library(ggplot2)

# 假设你的原始数据是df,包含lon(经度)、lat(纬度)、wind_speed(风速)、wind_dir(风向,单位度)
# 手动按五大湖划分区域(这里示例用经度切分,你可以换成更精准的分组逻辑)
df$lake_region <- cut(df$lon, breaks = 5, labels = c("苏必利尔湖", "密歇根湖", "休伦湖", "伊利湖", "安大略湖"))

# 按区域计算平均值
summary_df <- df %>%
  group_by(lake_region) %>%
  summarize(
    avg_lon = mean(lon),
    avg_lat = mean(lat),
    avg_wind_speed = mean(wind_speed),
    avg_wind_dir = mean(wind_dir)
  ) %>%
  # 把风向转换成u/v分量(geom_quiver需要的是x/y方向的向量)
  mutate(
    u = avg_wind_speed * cos(avg_wind_dir * pi/180),
    v = avg_wind_speed * sin(avg_wind_dir * pi/180)
  )

# 绘制地图+大箭头
ggplot() +
  # 先叠加五大湖的底图(假设你有对应的sf格式数据great_lakes_sf)
  geom_sf(data = great_lakes_sf, fill = "#a8d1ff") +
  # 用汇总后的平均数据画大箭头,手动调大size让箭头更醒目
  geom_quiver(
    data = summary_df,
    aes(x = avg_lon, y = avg_lat, u = u, v = v, color = avg_wind_speed),
    size = 3,  # 控制箭杆的粗细和长度基础值
    vecsize = 0.3  # 控制箭头头部与箭杆的比例,数值越小箭头头部相对越小
  ) +
  scale_color_viridis_c(name = "平均风速")

方法2:自动聚类分组(适合不想手动划分的情况)

用k-means聚类对经纬度进行分组,自动生成3-5个区域,代码更灵活:

set.seed(123) # 设置随机种子保证结果可重复
# 对经纬度做k-means聚类,分成5组
clusters <- kmeans(df[, c("lon", "lat")], centers = 5)
df$cluster <- as.factor(clusters$cluster)

# 按聚类组汇总数据
summary_df <- df %>%
  group_by(cluster) %>%
  summarize(
    avg_lon = mean(lon),
    avg_lat = mean(lat),
    avg_wind_speed = mean(wind_speed),
    avg_wind_dir = mean(wind_dir)
  ) %>%
  mutate(
    u = avg_wind_speed * cos(avg_wind_dir * pi/180),
    v = avg_wind_speed * sin(avg_wind_dir * pi/180)
  )

# 后续绘图代码和上面一致

问题2:部分箭头尺寸过小,搞懂vecsize参数的真实作用

你困惑的点其实是把vecsize的功能理解错了——vecsize控制的是箭头头部和箭杆的比例,不是箭杆本身的长度!

为什么部分箭头小?

箭头的整体视觉大小主要由u和v的数值决定(也就是风速转换后的x/y向量分量):如果某个点的风速很小,那么u和v的数值就会很小,箭杆自然短,看起来整个箭头就小。vecsize只是调整箭头头部的长度相对于箭杆长度的比例,比如vecsize=0.3意味着箭头头部的长度是箭杆长度的30%,箭杆短的话,箭头头部也会跟着变小。

解决方案

根据你的需求,有两种调整方式:

  1. 缩放向量分量,让小风速的箭头也能看清
    手动给u和v乘以一个系数,放大所有箭头的基础长度:

    df <- df %>%
      mutate(
        # 乘以0.5是示例系数,你可以根据你的数据范围调整,比如风速单位是m/s的话,乘1-2都可以
        u = wind_speed * 0.5 * cos(wind_dir * pi/180),
        v = wind_speed * 0.5 * sin(wind_dir * pi/180)
      )
    

    然后绘图时再配合调整vecsize,让箭头头部比例合适:

    geom_quiver(
      aes(x = lon, y = lat, u = u, v = v, color = wind_speed),
      vecsize = 0.25, # 小风速箭头的头部也不会太突兀
      alpha = 0.8
    )
    
  2. 统一箭杆长度,用颜色单独表示风速
    如果不需要用箭杆长度体现风速,只需要颜色区分,可以把向量转换成单位向量(方向不变,长度统一),然后用size参数固定箭杆粗细:

    df <- df %>%
      mutate(
        # 计算单位向量
        dir_rad = wind_dir * pi/180,
        u = cos(dir_rad),
        v = sin(dir_rad)
      )
    
    ggplot() +
      geom_sf(data = great_lakes_sf) +
      geom_quiver(
        data = df,
        aes(x = lon, y = lat, u = u, v = v, color = wind_speed),
        size = 1.5, # 统一箭杆粗细
        vecsize = 0.3
      ) +
      scale_color_viridis_c(name = "风速")
    

另外补充下vecsize的官方说明:默认NULL时,如果你的数据是规则网格(比如经纬度间隔一致的格点数据),ggplot会自动调整vecsize避免箭头重叠;如果是不规则散点数据,就用默认比例(大概0.2),这时候手动设置固定值会更可控。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:35:00