如何通过wind_ras_data的Extent范围过滤vec数据框?
问题描述
我有两个包含x、y(经纬度)列的数据框,分别名为wind_ras_data和vec。我希望通过wind_ras_data的Extent范围过滤vec数据框中的数据。
当前范围信息:
> extent(wind_ras_data) class : Extent xmin : -13519474 xmax : -13030428 ymin : 3809653 ymax : 4129625 > extent(vec) class : Extent xmin : -13579579 xmax : -12995375 ymin : 3740029 ymax : 4168294
尝试过以下无效代码:
vec_within <- vec %>% filter(extent(vec) %in% extent(wind_ras_data))
工作流代码:
wind_ras_data <- as.data.frame(rasterToPoints(final_ras_wind)) %>% pivot_longer(!c(x,y), names_to = "date", values_to = "wind") coordinates(wind_ras_data) <- c('x', 'y') # 将经纬度坐标的投影设为默认的EPSG:4326 proj4string(wind_ras_data) <- CRS("+init=epsg:4326") # 将坐标转换为使用的度量系统(EPSG:3857) wind_ras_data<-spTransform(wind_ras_data,CRS("+init=EPSG:3857")) vec <- vec_data %>% mutate(angle = (270 - (atan2(u, v) * (180/pi))%%360)) %>% dplyr::select(x, everything()) %>% dplyr::select(!c(u,v)) coordinates(vec) <- c('x', 'y') # 将经纬度坐标的投影设为默认的EPSG:4326 proj4string(vec) <- CRS("+init=epsg:4326") # 将坐标转换为使用的度量系统(EPSG:3857) vec<-spTransform(vec,CRS("+init=EPSG:3857")) vec_within <- vec %>% filter(gWithin(vec, wind_ras_data, byId = TRUE))
解决方案
问题分析
- 原代码
extent(vec) %in% extent(wind_ras_data)是判断两个范围对象是否完全相等,而非逐个判断vec中的点是否在wind_ras_data的范围内,因此无法实现过滤需求。 gWithin(vec, wind_ras_data, byId = TRUE)返回的是拓扑关系矩阵,直接放入filter会导致逻辑错误,且没有针对范围做判断。
方法1:直接通过坐标范围过滤
先获取wind_ras_data的范围参数,再基于x、y坐标筛选vec中的点:
# 获取wind_ras_data的范围 wind_ext <- extent(wind_ras_data) # 用base R的subset直接处理Spatial对象 vec_within <- subset(vec, x >= wind_ext@xmin & x <= wind_ext@xmax & y >= wind_ext@ymin & y <= wind_ext@ymax) # 或转成数据框用dplyr过滤后转回空间对象 vec_df <- as.data.frame(vec) vec_df_filtered <- vec_df %>% filter(x >= wind_ext@xmin, x <= wind_ext@xmax, y >= wind_ext@ymin, y <= wind_ext@ymax) # 恢复空间属性 coordinates(vec_df_filtered) <- c("x", "y") proj4string(vec_df_filtered) <- proj4string(vec)
方法2:用raster包的crop函数(最简洁)
crop函数可直接对空间对象进行范围裁剪,自动保留范围内的点:
vec_within <- crop(vec, extent(wind_ras_data))
验证结果
可以通过查看裁剪后的范围确认效果:
extent(vec_within)
内容的提问来源于stack exchange,提问作者Eizy
相关产品推荐
相关产品推荐

