如何在0.05分辨率网格上聚合并绘制大型渔业作业数据集?
问题描述
我正在处理一个包含坐标和渔业作业强度(HF)的数据集,共2985412行,样本数据如下:
Year Month Type SI_LONG SI_LATI HF 2008 04 OTB_DEF_>=70_0 -4.88 46.84 0.617 2008 04 OTB_DEF_>=70_0 -4.91 46.83 0.4 2008 04 OTB_DEF_>=70_0 -4.96 46.85 1 2008 04 OTB_DEF_>=70_0 -5.01 46.84 1.02 2008 04 OTB_DEF_>=70_0 -5.01 46.92 1 2008 04 OTB_DEF_>=70_0 -4.95 46.98 1 2008 04 OTB_DEF_>=70_0 -4.92 46.96 1.02 2008 04 OTB_DEF_>=70_0 -4.97 46.93 1.02 2008 04 OTB_DEF_>=70_0 -4.96 46.97 0.167 2008 04 OTB_DEF_>=70_0 -5 46.94 0.833
我需要将数据聚合到0.05分辨率的网格上,每个网格像素代表对应区域内所有点的HF均值,最终生成规整的可视化图。但目前用R代码生成的图存在像素大小不一、重叠的问题,代码如下:
# Map and grid limits grid_xmin <- -6 grid_xmax <- 0 grid_ymin <- 42 grid_ymax <- 48 grid_limit <- extent(c(grid_xmin,grid_xmax,grid_ymin,grid_ymax)) # Resolution of grid grid <- raster(grid_limit) res(grid) <- 0.05 crs(grid) <- "+proj=longlat +datum=WGS84" # Create grid polygon gridpolygon <- rasterToPolygons(grid) gridpolygon$layer <- c(1:length(gridpolygon$layer)) gridpolygon_sf <- st_as_sf(gridpolygon) #Transform to sf object points_sf <- st_as_sf(HF_filter[,c("SI_LONG","SI_LATI","HF","LE_MET_level6","Year","Month")], coords = c("SI_LONG","SI_LATI"),crs="+proj=longlat +datum=WGS84") points_sf <- points_sf[st_intersects(points_sf,gridpolygon_sf) %>% lengths > 0,] points_df <- st_join(points_sf,gridpolygon_sf) %>% as.data.frame %>% dplyr::select(-geometry) ## Aggregate at the cell level polyg_sf <- inner_join(gridpolygon_sf,points_df)%>% group_by(layer) %>% dplyr::summarise(fishing_effort = mean(HF)) #Plot ggplot() + geom_sf(data=polyg_sf,aes(fill = fishing_effort,col=fishing_effort))+ #geom_sf(data=points_sf,size=0.1)+ geom_sf(data=mapBase)+ coord_sf(xlim = c(-6,0), ylim = c(43,48), expand = FALSE)+ scale_fill_distiller(palette = "Spectral")+ scale_color_distiller(palette = "Spectral")
改进方案
问题根源
原方法通过rasterToPolygons生成网格多边形后进行空间连接聚合,不仅处理百万级数据效率低下,还可能因坐标系转换、多边形边缘计算误差,导致绘图时出现不规则重叠。更高效的方式是直接基于栅格填充值,或用sf生成规则网格后聚合。
方法一:栅格包直接聚合(高效处理大数据)
直接将点数据的HF均值赋值到对应栅格单元,避免多边形转换的额外开销:
library(raster) library(dplyr) library(ggplot2) library(sf) # 1. 准备栅格模板 grid_xmin <- -6 grid_xmax <- 0 grid_ymin <- 42 grid_ymax <- 48 grid <- raster(extent(grid_xmin, grid_xmax, grid_ymin, grid_ymax), res = 0.05, crs = "+proj=longlat +datum=WGS84") # 2. 将点数据聚合到栅格(计算每个单元的HF均值) points_data <- HF_filter %>% select(SI_LONG, SI_LATI, HF) raster_hf <- rasterize(points_data[,c("SI_LONG", "SI_LATI")], grid, field = points_data$HF, fun = mean) # 3. 转换为sf多边形用于ggplot绘图 raster_sf <- rasterToPolygons(raster_hf, na.rm = TRUE) %>% st_as_sf() names(raster_sf)[1] <- "fishing_effort" # 4. 绘图 ggplot() + geom_sf(data = raster_sf, aes(fill = fishing_effort), color = NA) + # 去掉边框避免重叠 geom_sf(data = mapBase) + coord_sf(xlim = c(-6, 0), ylim = c(43, 48), expand = FALSE) + scale_fill_distiller(palette = "Spectral", na.value = "transparent") + theme_minimal()
方法二:sf生成规则网格聚合(灵活适配后续分析)
如果需要保留网格的sf对象用于后续操作,用st_make_grid生成规则网格,再进行空间连接聚合:
library(sf) library(dplyr) library(ggplot2) # 1. 生成规则网格 grid_bbox <- st_bbox(c(xmin = -6, xmax = 0, ymin = 42, ymax = 48)) %>% st_as_sfc() grid_sf <- st_make_grid(grid_bbox, cellsize = 0.05, what = "polygons") %>% st_as_sf() grid_sf$cell_id <- 1:nrow(grid_sf) # 2. 转换点数据为sf points_sf <- st_as_sf(HF_filter, coords = c("SI_LONG", "SI_LATI"), crs = "+proj=longlat +datum=WGS84") # 3. 空间连接并聚合(计算每个网格的HF均值) polyg_sf <- st_join(grid_sf, points_sf, join = st_contains) %>% group_by(cell_id) %>% summarise(fishing_effort = mean(HF, na.rm = TRUE)) %>% filter(!is.na(fishing_effort)) # 过滤无数据的网格 # 4. 绘图 ggplot() + geom_sf(data = polyg_sf, aes(fill = fishing_effort), color = NA) + geom_sf(data = mapBase) + coord_sf(xlim = c(-6, 0), ylim = c(43, 48), expand = FALSE) + scale_fill_distiller(palette = "Spectral") + theme_minimal()
关键优化点
- 移除网格边框:绘图时设置
color = NA,避免相邻网格边框重叠导致视觉不规则。 - 高效聚合逻辑:用
rasterize或st_make_grid+st_join替代原方法的多次转换,减少计算误差和性能消耗。 - 过滤空值单元:移除无数据的网格,避免空值区域干扰可视化效果。
内容的提问来源于stack exchange,提问作者JulietteTC
相关产品推荐
相关产品推荐

