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

使用ggplot2绘制毛里求斯等值线图时stat_contour报错求助

问题:基于毛里求斯底图绘制等值线图无结果,出现警告

我尝试基于毛里求斯底图,利用3个站点数据绘制基础等值线图,但出现以下警告信息:

Warning messages:
1: stat_contour(): Zero contours were generated
2: In min(x) : no non-missing arguments to min; returning Inf
3: In max(x) : no non-missing arguments to max; returning -Inf

当前输出图没有等值线,期望生成类似Surfer软件的带等值线的图,以下是我的完整代码:

library(ggplot2)
library(sf)
library(akima)
library(rnaturalearth)
library(rnaturalearthdata)

world <- ne_countries(scale = "medium", returnclass = "sf")
mauritius <- world[world$name == "Mauritius", ]

# Convert the Mauritius data to a spatial object
mauritius_sf <- st_as_sf(mauritius)

# Load the station data
stations <- data.frame(
  lon = c(57.5, 57.6, 57.7),   
  lat = c(-20.1, -20.2, -20.3), 
  value = c(30, 15, 26)         
)

# Convert the station data to a spatial object
stations_sf <- st_as_sf(stations, coords = c("lon", "lat"), crs = 4326)

# Interpolate the data using akima with a higher resolution
interp_data <- with(stations, interp(lon, lat, value, xo = seq(min(lon), max(lon), length.out = 500), yo = seq(min(lat), max(lat), length.out = 500)))

# Convert the interpolated data to a dataframe
interp_df <- data.frame(expand.grid(x = interp_data$x, y = interp_data$y), z = as.vector(interp_data$z))

# Remove missing and infinite values from the interpolated data
interp_df <- na.omit(interp_df)
interp_df <- interp_df[!is.infinite(interp_df$z), ]

# Check if the interpolated data is empty and plot using ggplot2
if (nrow(interp_df) > 0) {
  ggplot() +
    geom_sf(data = mauritius_sf, fill = "grey90", color = "black") + 
    geom_contour(aes(x = x, y = y, z = z), data = interp_df, bins = 10) +
    geom_point(data = as.data.frame(stations), aes(x = lon, y = lat), color = "red", size = 3) +
    coord_sf(xlim = c(57.3, 57.9), ylim = c(-20.55, -19.95), expand = FALSE) +
    labs(title = "Contour Plot over Mauritius Map", x = "Longitude", y = "Latitude")
} else {
  print("No data available for contour plot.")
}

问题原因与解决方案

核心问题

  1. 插值范围与绘图范围不匹配:插值仅在3个站点的经纬度最小-最大值范围内进行,但绘图时的坐标范围远大于此,导致有效插值数据仅集中在极小区域,无法生成等值线。
  2. 凸包外插值被删除:akima::interp仅在数据点的凸包内生成有效插值,凸包外为NA,后续的na.omit直接删除了这些NA值,进一步缩小了有效数据范围。

修正后的代码

将插值范围调整为与绘图坐标范围一致,同时保留凸包外的插值(即使是NA,后续绘图时会自动忽略,但等值线能在有效区域生成),另外添加填充层让效果更接近Surfer:

library(ggplot2)
library(sf)
library(akima)
library(rnaturalearth)
library(rnaturalearthdata)

# 获取毛里求斯底图
world <- ne_countries(scale = "medium", returnclass = "sf")
mauritius_sf <- world[world$name == "Mauritius", ]

# 站点数据
stations <- data.frame(
  lon = c(57.5, 57.6, 57.7),   
  lat = c(-20.1, -20.2, -20.3), 
  value = c(30, 15, 26)         
)

# 设置插值范围(与绘图范围一致)
x_range <- seq(57.3, 57.9, length.out = 500)
y_range <- seq(-20.55, -19.95, length.out = 500)

# 插值(extrapolate=TRUE允许凸包外插值,避免过多NA)
interp_data <- with(stations, interp(lon, lat, value, 
                                     xo = x_range, yo = y_range,
                                     extrapolate = TRUE))

# 转换为数据框
interp_df <- as.data.frame(interp2xyz(interp_data, data.frame = TRUE))

# 绘图
ggplot() +
  # 毛里求斯底图
  geom_sf(data = mauritius_sf, fill = "grey90", color = "black") + 
  # 等值线填充(更接近Surfer效果)
  geom_contour_filled(aes(x = x, y = y, z = z), data = interp_df, bins = 10) +
  # 等值线线条
  geom_contour(aes(x = x, y = y, z = z), data = interp_df, bins = 10, color = "white", linewidth = 0.3) +
  # 站点标记
  geom_point(data = stations, aes(x = lon, y = lat), color = "red", size = 3) +
  # 坐标范围锁定
  coord_sf(xlim = c(57.3, 57.9), ylim = c(-20.55, -19.95), expand = FALSE) +
  labs(title = "等值线图(毛里求斯)", x = "经度", y = "纬度") +
  theme_minimal()

关键调整点

  • 插值范围改为和绘图的xlim/ylim一致,确保插值覆盖整个绘图区域。
  • 添加extrapolate = TRUE参数,允许在数据凸包外进行插值,减少NA值。
  • 使用interp2xyz更便捷地将插值结果转换为数据框。
  • 增加geom_contour_filled生成填充等值线,更接近Surfer软件的可视化效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 22:05:00