使用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.") }
问题原因与解决方案
核心问题
- 插值范围与绘图范围不匹配:插值仅在3个站点的经纬度最小-最大值范围内进行,但绘图时的坐标范围远大于此,导致有效插值数据仅集中在极小区域,无法生成等值线。
- 凸包外插值被删除:
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
相关产品推荐
相关产品推荐

