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

R语言合并蒙特卡洛模拟点地图及计算KDE栅格均值

解决蒙特卡洛模拟栅格均值计算与点合并问题

嘿,我注意到你已经用purrr::map_dfr搞定了50次蒙特卡洛模拟点的合并,但在处理KDE栅格均值的时候遇到了麻烦。先帮你把点合并的部分再确认下,然后重点解决栅格的问题!

一、模拟点合并的优化(已解决,补充细节)

你提到用purrr::map_dfr合并点,其实可以给每个模拟结果加个iteration标识列,这样后续可视化或者分析时还能区分不同批次的模拟点,代码更清晰:

# 合并所有模拟点,并添加迭代编号列
all_points <- purrr::map_dfr(monte, ~., .id = "iteration")

得到的all_points就是包含所有50次模拟点的sf对象,直接用ggplot2或者基础plot()就能画出合并后的地图了。

二、KDE栅格均值计算的核心解决方案

首先得明确:计算多个栅格的均值,前提是所有栅格的范围、分辨率、CRS必须完全一致。下面分步骤给你拆解:

1. 先确保栅格参数一致

假设你已经生成了每个模拟对应的KDE栅格,存放在列表kde_raster_list里(比如用map(monte, ~st_kde(.x))生成)。先检查所有栅格的参数是否统一:

# 提取所有栅格的关键属性
raster_props <- purrr::map_df(kde_raster_list, function(r) {
  tibble(
    crs = st_crs(r)$wkt,
    xmin = st_bbox(r)[["xmin"]],
    xmax = st_bbox(r)[["xmax"]],
    ymin = st_bbox(r)[["ymin"]],
    ymax = st_bbox(r)[["ymax"]],
    res_x = st_resolution(r)[1],
    res_y = st_resolution(r)[2]
  )
})

# 检查是否所有栅格属性都和第一个一致
all(raster_props == raster_props[1, ])

如果返回TRUE,直接进入下一步;如果是FALSE,需要用st_warp()把所有栅格对齐到第一个栅格的参数:

# 对齐所有栅格到第一个栅格的范围、分辨率和CRS
kde_raster_aligned <- purrr::map(kde_raster_list, ~st_warp(.x, kde_raster_list[[1]]))

2. 两种计算均值的方法

方法一:基于sf数据框分组计算(易理解)

把每个栅格转换为带KDE值的sf数据框,然后按栅格单元(geometry)分组求均值:

# 将所有对齐后的栅格转为长格式数据框,保留迭代标识
kde_df <- purrr::map_dfr(kde_raster_aligned, function(r) {
  st_as_sf(r, as_points = FALSE) %>%  # 把栅格转为sf多边形(每个单元是一个多边形)
    mutate(kde_value = as.vector(r)) %>%  # 提取每个单元的KDE值
    select(geometry, kde_value)
}, .id = "iteration")

# 按栅格单元分组,计算均值
kde_mean_df <- kde_df %>%
  group_by(geometry) %>%
  summarise(mean_kde = mean(kde_value, na.rm = TRUE)) %>%
  ungroup()

# 可选:转回栅格格式(如果需要栅格输出)
kde_mean_raster <- st_rasterize(kde_mean_df, template = kde_raster_list[[1]])

方法二:用terra包高效计算(推荐)

如果你的栅格是terra::SpatRaster格式(现在sf生态更推荐配合terra处理栅格),可以直接用集合操作计算均值,效率更高:

library(terra)

# 将栅格列转为SpatRaster集合
kde_terra_collection <- sprc(kde_raster_list)

# 一键计算所有栅格的均值
kde_mean_raster <- mean(kde_terra_collection, na.rm = TRUE)

# 可选:转回sf格式的栅格
kde_mean_sf <- st_as_sf(kde_mean_raster)

三、完整流程示例(包含KDE生成)

如果还没生成KDE栅格,这里给你补全整个流程的代码,确保能跑通:

library(sf)
library(tidyverse)
library(terra)
library(spatstat)  # 用于KDE计算,也可以用sf::st_kde

# 你的原始数据和模拟代码
mydf <- structure(list(x = c(555624, 572481, 703318, 700818, 571713, 559113, 731606, 604972), y = c(218959, 184051, 233180, 233603, 182307, 153136, 279015, 200216), acc.=c(120.35451, 128.74603, 74.63894, 73.96213, 93.63799, 257.49205, 53.59192, 190.78791)), .Names = c("x","y","acc."), class = "data.frame", row.names = c(NA, -8L))
mydf = st_as_sf(mydf, coords=c("x","y"), crs=21781)
n = 50 

move_point <- function(point, maxdistance){
  n_points <- length(point)
  angle_deg <- runif(n_points,1,360)
  distance <- rnorm(n_points,mean = 0,sd = maxdistance/2)
  angle_rad <- (angle_deg * pi) / (180)
  point_old <- st_coordinates(point)
  xoffset <- cos(angle_rad) * distance
  yoffset <- sin(angle_rad) * distance
  point_new <- point_old + matrix(c(xoffset,yoffset), ncol = 2)
  point_new <- point_new %>% split(1:nrow(.)) %>% map(~st_point(.x))%>% st_sfc()
  point_new
}

monte <- purrr::map(1:n, function(x){
  at <-move_point(mydf$geometry, mydf$acc.)
  st_as_sf(at, crs=21781)
})

# 1. 合并所有模拟点
all_points <- purrr::map_dfr(monte, ~., .id = "iteration")

# 2. 生成统一参数的KDE栅格列
# 先创建覆盖所有点的统一窗口(确保所有KDE栅格范围一致)
window <- st_bbox(all_points) %>%
  st_as_sfc() %>%
  as("owin")

# 生成每个模拟的KDE栅格
kde_raster_list <- purrr::map(monte, function(sf_points) {
  # 转换为spatstat的ppp对象
  ppp_points <- as(sf_points, "ppp")
  # 计算KDE(用Diggle带宽,也可以自定义sigma)
  kde <- density(ppp_points, sigma = "bw.diggle", window = window)
  # 转换为terra的SpatRaster并设置CRS
  raster(kde) %>%
    set.crs(st_crs(sf_points)$wkt)
})

# 3. 计算KDE栅格均值
kde_terra_collection <- sprc(kde_raster_list)
kde_mean_raster <- mean(kde_terra_collection, na.rm = TRUE)

# 4. 可视化:合并点 + 均值KDE
ggplot() +
  geom_sf(data = st_as_sf(kde_mean_raster), aes(fill = mean), alpha = 0.5) +
  geom_sf(data = all_points, size = 0.5, alpha = 0.3) +
  scale_fill_viridis_c(option = "magma") +
  theme_minimal() +
  labs(title = "50次蒙特卡洛模拟点合并与KDE均值", fill = "均值KDE值")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 09:38:14