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

如何为外部点匹配克里金插值生成的等时线/等值带

问题:为外部点数据集匹配克里金插值的等时线区间

我在硕士论文中开展克里金空间插值工作,通过普通克里金插值绘制农业从近东向欧洲传播的等时线地图,并用ggplot完成可视化。当前需要给未参与插值的外部红色点数据集新增一列,标记每个点所属的等时线区间(例如巴利阿里群岛的红点对应(7000,7500]区间)。

尝试将ggplot中的等时线转为多边形后,用st_intersect()或st_contains()进行点匹配,但无法从ggplot地图中生成等时线多边形,尝试过ggplot_build提取图层转sf对象但未成功。以下是使用公开数据复现的完整代码:

library(gstat)
library(sf)
library(readr)
library(tidyverse)
library(rnaturalearth)

##Data
no2 <- read_csv(system.file("external/no2.csv", package = "gstat"), show_col_types = FALSE)
no2_sf <- st_as_sf(no2, crs = "OGC:CRS84", coords = c("station_longitude_deg", "station_latitude_deg")) 
no2_sf <- st_transform(no2_sf, 32632)


##Kriging
#Interpolation raster
no2_bbox <- st_bbox(no2_sf)
cell_size <- 10000
x <- seq(no2_bbox$xmin, no2_bbox$xmax, by=cell_size)
y <- seq(no2_bbox$ymin, no2_bbox$ymax, by=cell_size)
no2_grid <- expand.grid(x=x, y=y)
no2_grid$tmp <- 1
plot(no2_grid$x, no2_grid$y, pch=19, cex=0.1)
no2_grid <- st_as_sf(no2_grid, coords = c("x","y"), crs = st_crs(no2_sf))
st_crs(no2_grid) <- st_crs(no2_sf)

#Variogram
no2_sample_variogram <- gstat::variogram(NO2~1, no2_sf)
plot(no2_sample_variogram, plot.numbers = TRUE)
no2_model_variogram <- vgm(psill = 16, "Exp", range = 200000, nugget = 1)
plot(no2_sample_variogram, no2_model_variogram)
no2_fit_variogram <- fit.variogram(no2_sample_variogram, no2_model_variogram)
plot(no2_sample_variogram, no2_fit_variogram)

#Ordinary Kriging
no2_sf <- no2_sf[!duplicated(no2_sf$geometry),] #check which observation were removed
no2_kriging <- gstat::krige(NO2~1, no2_sf, no2_grid, no2_fit_variogram)

no2_kriging$x <- st_coordinates(no2_kriging)[,1]
no2_kriging$y <- st_coordinates(no2_kriging)[,2]

##Ggplot
points <- data.frame(x = runif(10, min = no2_bbox$xmin, max = no2_bbox$xmax), y = runif(10, min = no2_bbox$ymin, max = no2_bbox$ymax))
points <- st_as_sf(points, coords = c("x","y"), crs = st_crs(32632))
  
germany  <- ne_countries(scale = "medium", returnclass = "sf", country = "Germany")
germany <- st_transform(germany, 32632)

ggplot()+  geom_contour_filled(data = no2_kriging, aes(x = x, y = y, z=var1.pred))+  geom_sf(data = germany,  fill = "transparent", color = "black")+  geom_sf(data = points, size = 0.5, color = "red")

解决方案:直接生成等时线多边形(无需从ggplot提取)

不要从ggplot图层反向提取等值带,直接基于克里金插值结果生成等值带多边形,再与外部点做空间匹配,步骤如下:

1. 安装并加载isoband包

isoband是geom_contour_filled背后的核心包,可以直接从网格数据生成等值带多边形,确保结果与ggplot可视化完全一致:

install.packages("isoband")
library(isoband)

2. 从克里金插值结果生成等值带sf对象

将插值后的网格数据转换为矩阵,再生成等值带多边形:

# 提取网格的x、y坐标和插值预测值矩阵
x_vals <- unique(no2_kriging$x)
y_vals <- unique(no2_kriging$y)
z_matrix <- matrix(no2_kriging$var1.pred, nrow = length(y_vals), ncol = length(x_vals))

# 设置等值带区间(与ggplot的binwidth保持一致,这里用自动计算,也可手动指定)
# 手动指定区间示例:breaks <- seq(min(no2_kriging$var1.pred), max(no2_kriging$var1.pred), by = 5)
breaks <- isobreaks(z_matrix, binwidth = 5) # binwidth需和geom_contour_filled的参数匹配

# 生成等值带多边形并转为sf对象
iso_polygons <- isobands(x_vals, y_vals, z_matrix, breaks, breaks[-1])
iso_sf <- iso_to_sfg(iso_polygons) %>% 
  st_sfc(crs = st_crs(no2_kriging)) %>% 
  st_sf() %>% 
  mutate(interval = names(iso_polygons)) # 添加区间标签,格式与ggplot一致

3. 空间匹配外部点与等值带区间

用st_join()完成点与多边形的空间连接,自动为每个点添加所属的区间:

# 空间连接,保留点的所有属性,新增interval列
points_with_interval <- st_join(points, iso_sf, join = st_intersects)

# 查看匹配结果
head(points_with_interval)

4. 验证匹配准确性(可选)

将生成的等值带多边形和带区间的点一起绘制,确认匹配正确:

ggplot() +
  geom_sf(data = iso_sf, aes(fill = interval)) +
  geom_sf(data = germany, fill = "transparent", color = "black") +
  geom_sf(data = points_with_interval, color = "red", size = 1) +
  labs(fill = "NO2 Interval")

关键注意事项

  • 确保breaks的binwidth与geom_contour_filled的参数完全一致,保证区间划分完全匹配
  • 该方法生成的区间标签格式(如(10,15])与ggplot完全相同,直接满足你的需求
  • 避免了从ggplot图层提取数据的繁琐操作,结果更可靠

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 05:33:16