如何用Geopandas结合Basemap批量判断点是否位于陆地?
解决GeoDataFrame批量判断点是否在陆地的问题
首先,先帮你修正Basemap的代码问题——你遇到的报错是因为Basemap的坐标转换函数map()返回的是两个数组(x和y投影坐标),不能直接链式调用is_land。修正后的代码可以批量处理,不用遍历:
from mpl_toolkits.basemap import Basemap # 初始化Basemap map = Basemap( area_thresh=10, resolution="i", llcrnrlon=0., llcrnrlat=-80., urcrnrlon=360, urcrnrlat=80 ) # 先批量转换经纬度到投影坐标,得到x、y两个数组 x, y = map(ong_assets_gdf.geometry.x, ong_assets_gdf.geometry.y) # 再用is_land批量判断,直接生成布尔列 ong_assets_gdf['onshore'] = map.is_land(x, y)
不过得提醒你:Basemap已经停止维护了,后续可能会遇到兼容性问题,更推荐用下面这些现代、可扩展的方案,完全满足你“避免遍历”的需求:
方案1:GeoPandas + 自然地球陆地矢量数据(最推荐)
这个方案纯用GeoPandas的空间操作,批量处理效率高,而且数据可按需选择分辨率:
import geopandas as gpd # 读取自然地球的陆地数据集(默认是1:110m低分辨率,也可以用1:10m高分辨率) # 1:10m数据可以直接读取在线源:gpd.read_file("https://naciscdn.org/naturalearth/10m/physical/ne_10m_land.zip") land = gpd.read_file(gpd.datasets.get_path('naturalearth_land')) # 确保你的点数据和陆地数据坐标系一致(都是WGS84,EPSG:4326) ong_assets_gdf = ong_assets_gdf.set_crs(epsg=4326, allow_override=True) # 批量判断点是否在陆地内:把所有陆地多边形合并成一个,然后用within批量检查 ong_assets_gdf['onshore'] = ong_assets_gdf.geometry.within(land.unary_union)
补充优化:
如果你的数据量极大,可以考虑:
- 用
geopandas.sjoin做空间连接,然后通过匹配标记判断,适合并行处理 - 选择合适分辨率的陆地数据,平衡精度和速度
方案2:Rasterio + 高分辨率陆地栅格数据
如果需要更高精度(比如米级),可以用栅格数据批量查询:
import rasterio # 假设你有一个陆地栅格文件(1=陆地,0=海洋,比如NASA MODIS陆地覆盖数据) with rasterio.open('high_res_land_mask.tif') as src: # 批量转换经纬度到栅格的行列号 rows, cols = src.index(ong_assets_gdf.geometry.x, ong_assets_gdf.geometry.y) # 批量读取栅格值,生成陆地标记 ong_assets_gdf['onshore'] = src.read(1)[rows, cols] == 1
这个方案适合对精度要求极高的场景,同样是批量操作,无需遍历。
内容的提问来源于stack exchange,提问作者ZedIsDead
相关产品推荐
相关产品推荐

