当前位置: 首页 > news >正文

Python地理数据处理实战:Geopandas读写Shapefile全攻略

1. 项目概述:为什么你需要掌握Geopandas与Shapefile

如果你正在用Python处理地理空间数据,却还在用GDAL/OGR那些复杂的C++接口,或者对着ArcGIS的桌面软件发愁,那你真的应该试试Geopandas。它本质上是一个让地理数据处理变得像用Pandas处理表格数据一样简单的Python库。而Shapefile,作为地理信息系统(GIS)领域几十年来事实上的标准矢量数据格式,几乎是你无法绕开的一环。把这两者结合起来,意味着你可以用几行Python代码,完成数据读取、空间分析、可视化到结果导出的一系列工作,效率提升不是一点半点。

我最初接触Geopandas是因为一个城市数据分析项目,需要处理成千上万个多边形区域的人口统计数据。用传统的GIS软件,每次数据更新都要进行繁琐的导入、连接属性、导出操作,不仅慢,还容易出错。切换到Geopandas后,整个流程被脚本化,从数据清洗、空间连接到生成专题地图,全部自动化完成。这让我意识到,对于需要重复、批量处理空间数据,或者将空间分析嵌入到更大数据科学流水线中的场景,Geopandas几乎是目前Python生态下的最优解。

简单来说,这个教程的目标是让你能快速上手,独立完成使用Geopandas读写Shapefile的核心操作。无论你是GIS专业的学生、从事城市规划、交通物流、环境科学的研究者,还是任何需要对带位置信息的数据进行分析的开发者,掌握这套工具都能让你事半功倍。接下来,我会从最基础的环境搭建讲起,一直深入到实际应用中的技巧和坑点。

2. 环境准备与核心库安装

工欲善其事,必先利其器。Geopandas的安装对于新手来说可能是第一个小门槛,因为它依赖一些底层的C库,不像纯Python包那样一条pip install就能轻松搞定。不过别担心,按照下面的步骤来,可以避开绝大多数坑。

2.1 安装策略与依赖解析

Geopandas的核心依赖包括:pandas(数据处理)、shapely(几何对象操作)、fiona(读写矢量数据,如Shapefile)、pyproj(坐标参考系统管理)以及matplotlib(绘图)。其中,fionashapely又依赖GEOS、GDAL等C/C++库。在Windows上直接pip安装这些包时,经常因为缺少编译环境或二进制轮子(wheel)而失败。

因此,最稳妥、最推荐的方法是使用Conda进行安装。Conda是一个跨平台的包和环境管理器,它不仅能管理Python包,还能管理那些底层的非Python依赖(如GDAL库)。Anaconda或更轻量化的Miniconda都行。

如果你坚持使用pip,特别是在Windows上,请务必前往 Unofficial Windows Binaries for Python Extension Packages 这个网站,手动下载对应你Python版本和系统架构(通常是win_amd64)的GDALFionaShapelyPyproj等包的.whl文件,然后用pip install 文件名.whl的方式本地安装。这个方法比较繁琐,且版本需要严格匹配。

注意:无论用哪种方式,都强烈建议创建一个独立的Conda环境或Python虚拟环境来安装Geopandas。这能避免与你系统上已有的其他包产生版本冲突。例如,使用conda create -n geo_env python=3.9创建一个名为geo_env、Python版本为3.9的新环境。

2.2 分步安装指南

这里给出最通用的Conda安装步骤:

  1. 安装或确保已安装Conda。如果你还没有,去Miniconda官网下载安装。

  2. 创建并激活新环境

    conda create -n geopandas_env python=3.9 conda activate geopandas_env
  3. 添加Conda-Forge频道并安装:Conda-Forge提供了更新更全的软件包。

    conda config --add channels conda-forge conda config --set channel_priority strict conda install geopandas

    这一条命令会自动解决所有依赖,包括GDAL、PROJ等。

  4. 验证安装:激活环境后,启动Python,尝试导入:

    import geopandas as gpd print(gpd.__version__)

    如果没有报错,并输出版本号(如0.12.0),恭喜你,安装成功。

实操心得:我遇到过在团队服务器上安装的情况,没有外网权限,Conda也无法直接使用。最终的解决方案是在一台能联网的相同系统环境的机器上,用conda pack命令将整个安装好的环境打包成tar.gz文件,然后上传到服务器解压使用。虽然麻烦,但一次搞定,团队所有人都能复用。

3. 深入理解Shapefile格式

在开始用代码操作之前,有必要了解一下你正在对付的“敌人”——Shapefile。它不是一个文件,而是一组至少由三个文件构成的集合,这种设计源于其古老的ESRI标准。

3.1 文件组成与结构

一个完整的Shapefile通常包含以下核心文件(扩展名不同):

  • .shp:主文件,存储几何要素(点、线、面)的空间信息,即坐标。
  • .shx:索引文件,存储几何要素在.shp文件中的位置索引,用于快速定位。
  • .dbf:属性表文件,以dBase IV格式存储每个几何要素对应的属性信息(如名称、人口、面积等)。

除了这三个必需文件,还常见一些辅助文件:

  • .prj:投影文件,存储坐标参考系统(CRS)信息,以WKT文本格式描述。这个文件至关重要,没有它,你的数据就只是一堆没有地理意义的数字坐标。
  • .cpg:可选,用于指定.dbf文件的字符编码(如UTF-8),在处理中文等非英文字符时非常重要。
  • .sbn/.sbx:空间索引文件,加速空间查询。

当你用Geopandas的gpd.read_file(‘data.shp’)时,它实际上会自动寻找并组合这些文件。你只需要提供.shp或任意一个核心文件的路径即可。

3.2 几何类型与属性表

Shapefile支持多种几何类型:

  • Point:点,代表一个位置。
  • MultiPoint:多点,一组点。
  • PolyLine:折线,由一系列有序点连接而成,代表道路、河流等。
  • Polygon:多边形,由闭合环定义,代表国家、湖泊、地块等区域。注意,多边形可以有“洞”(内环)。

属性表(.dbf)则是一个标准的表格,每一行对应一个几何要素,每一列是一个属性字段。Geopandas读取后,会创建一个GeoDataFrame对象,它继承自Pandas的DataFrame,但多了一个特殊的geometry列来存储几何对象。其他列就是属性数据,你可以像操作Pandas DataFrame一样进行筛选、分组、计算。

常见问题:为什么我读取的Shapefile中文显示乱码?这通常是因为.dbf文件的编码不是UTF-8,而可能是GBKGB2312。解决方法是在read_file时指定编码:gdf = gpd.read_file(‘data.shp’, encoding=‘GBK’)。如果不知道编码,可以尝试用chardet库检测,或者先用纯文本编辑器打开.dbf文件(但不要保存!)看看是否正常。

4. 读取Shapefile:从基础到高级

读取是第一步,Geopandas提供了非常灵活的接口。最基本的用法就是gpd.read_file()

4.1 基础读取与数据概览

假设你有一个名为counties.shp的县界数据文件,放在当前目录的data文件夹下。

import geopandas as gpd # 最基本读取方式 gdf = gpd.read_file(‘./data/counties.shp’) # 查看前几行数据 print(gdf.head()) # 查看数据结构信息 print(gdf.info()) # 查看坐标参考系统 print(gdf.crs)

gdf现在是一个GeoDataFramegdf.head()会显示前5行的属性和几何类型的简略信息。gdf.crs会告诉你数据的坐标系统,例如可能是EPSG:4326(WGS84经纬度)或EPSG:3857(Web墨卡托)。了解CRS对后续的空间计算和可视化至关重要。

4.2 高级读取技巧

  1. 选择性读取列:如果数据属性列很多,但你只关心其中几列,可以指定columns参数来提升读取速度。

    gdf = gpd.read_file(‘./data/counties.shp’, columns=[‘NAME’, ‘POPULATION’, ‘geometry’])
  2. 空间过滤(按范围读取):当数据文件很大时,你可以只读取特定地理范围内的要素。这需要先定义一个边界框。

    from shapely.geometry import box # 定义一个矩形范围 (minx, miny, maxx, maxy) bbox = box(116.0, 39.0, 117.0, 40.0) # 例如北京大致的范围 gdf_subset = gpd.read_file(‘./data/counties.shp’, bbox=bbox)

    这种方式比先读取全部数据再进行空间查询要高效得多,因为它利用了底层库的空间索引。

  3. 处理缺失的.prj文件:如果数据没有.prj文件,gdf.crs会是None。你必须手动指定正确的CRS,否则所有基于距离、面积的计算都是错误的。你需要知道数据原本的坐标系。例如,如果是GPS采集的经纬度,很可能是EPSG:4326

    gdf = gpd.read_file(‘./data/no_prj.shp’) if gdf.crs is None: gdf.set_crs(epsg=4326, inplace=True) # 假设是WGS84

    重要set_crs是给没有坐标系的数据定义一个坐标系。如果你知道数据有坐标系但读出来是错的,需要用to_crs进行转换

  4. 读取压缩文件:Geopandas支持直接读取.zip压缩包中的Shapefile,只要压缩包内保持了标准的文件结构。

    gdf = gpd.read_file(‘zip://./data/counties.zip’)

踩坑记录:有一次处理省级数据,直接读取后做面积计算,结果数值小得离谱。检查后发现crsEPSG:4326(度),而面积计算应在投影坐标系(如EPSG:32650,单位是米)下进行。所以必须先进行坐标转换:gdf_projected = gdf.to_crs(epsg=32650),然后再计算gdf_projected[‘area’] = gdf_projected.geometry.area

5. 创建与编辑Shapefile

除了读取,创建新的Shapefile或者修改现有数据也是常见需求。这对应着“写”操作。

5.1 从零开始创建GeoDataFrame和Shapefile

假设我们要创建一个包含几个城市点位信息的Shapefile。

import geopandas as gpd from shapely.geometry import Point import pandas as pd # 1. 准备属性数据 data = { ‘city’: [‘Beijing’, ‘Shanghai’, ‘Guangzhou’], ‘population’: [2154, 2489, 1868], # 单位:万 ‘lat’: [39.9042, 31.2304, 23.1291], ‘lon’: [116.4074, 121.4737, 113.2644] } df = pd.DataFrame(data) # 2. 创建几何列 geometry = [Point(lon, lat) for lon, lat in zip(df[‘lon’], df[‘lat’])] # 3. 创建GeoDataFrame,并指定CRS gdf = gpd.GeoDataFrame(df, geometry=geometry, crs=‘EPSG:4326’) # 4. 删除不必要的经纬度列(可选) gdf = gdf.drop(columns=[‘lat’, ‘lon’]) # 5. 查看并保存为Shapefile print(gdf) gdf.to_file(‘./output/chinese_cities.shp’, encoding=‘utf-8’)

关键点在于gpd.GeoDataFrame()的构造,它需要三个核心参数:一个Pandas DataFrame(属性)、一个几何对象序列、一个CRS。保存时使用to_file方法,指定encoding=‘utf-8’可以确保中文字符正常写入.dbf文件。

5.2 编辑现有数据并保存

更常见的场景是读取一个现有文件,修改后保存为新文件。

# 读取 gdf = gpd.read_file(‘./data/counties.shp’) # 进行一些操作,例如: # a) 属性计算 gdf[‘area_km2’] = gdf.to_crs(epsg=3857).geometry.area / 10**6 # 转换为Web墨卡托计算面积(近似) # b) 空间查询 from shapely.geometry import Point beijing = Point(116.4074, 39.9042) nearby_counties = gdf[gdf.geometry.distance(beijing) < 1.0] # 距离北京1度以内的县 # c) 几何操作 gdf[‘centroid’] = gdf.geometry.centroid # 计算每个多边形的质心 # 保存修改后的数据 # 保存全部 gdf.to_file(‘./output/counties_modified.shp’) # 只保存部分列和几何信息 gdf[[‘NAME’, ‘area_km2’, ‘geometry’]].to_file(‘./output/counties_simple.shp’)

注意事项to_file方法默认会覆盖同名文件。保存的Shapefile会包含.shp, .shx, .dbf, .prj等所有必要文件。如果你在GeoDataFrame中创建了新的几何列(如上面的centroid),默认情况下,只有第一个被设置为active geometry的几何列(通常是创建GeoDataFrame时指定的那个)会被写入.shp文件。其他几何列会作为WKT文本保存在.dbf的属性表中,这通常不是你想要的结果。如果你需要保存多个几何列,可能需要分别创建不同的GeoDataFrame来保存。

6. 坐标参考系统(CRS)的实战管理

CRS是地理数据的灵魂,管理不当会导致所有空间分析结果错误。Geopandas使用pyproj库来管理CRS。

6.1 理解CRS的两种表达

CRS有两种常见表达方式:

  • EPSG代码:数字编码,如4326代表WGS84地理坐标系,3857代表Web墨卡托投影坐标系。简洁通用。
  • WKT字符串:文本描述,非常详细但冗长。例如,gdf.crs的输出可能是一长串WKT。

6.2 核心操作:定义、查询与转换

  1. 定义CRS:当数据没有CRS或CRS错误时。

    # 方法1:使用EPSG代码 gdf.set_crs(epsg=4326, inplace=True) # 方法2:使用Proj字符串或WKT字符串 gdf.set_crs(‘+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs’, inplace=True)
  2. 查询CRS

    print(gdf.crs) # 输出CRS信息 print(gdf.crs.is_geographic) # 判断是否是地理坐标系(度) print(gdf.crs.is_projected) # 判断是否是投影坐标系(米)
  3. 转换CRS:这是最常用的操作,将数据从一个坐标系转换到另一个。

    # 从WGS84经纬度转换为UTM 50N带 (EPSG:32650),适用于中国大部分东部地区 gdf_projected = gdf.to_crs(epsg=32650) # 或者转换为Web墨卡托,用于网络地图 gdf_web = gdf.to_crs(epsg=3857)

    重要原则:所有基于长度、面积的计算(geometry.length,geometry.area),以及许多空间连接(spatial join)操作,都必须在投影坐标系下进行。地理坐标系(单位是度)下的计算没有物理意义。

常见问题排查:执行to_crs时报错,提示“RuntimeError: b‘no arguments in initialization list’”或类似。这通常是因为原始数据的CRS定义不完整或格式不被pyproj识别。可以尝试先强制定义一个公认的CRS(如EPSG:4326),再进行转换。或者,使用gdf.estimate_utm_crs()方法让Geopandas自动估算一个合适的UTM投影。

7. 空间分析与几何操作入门

读取和创建是基础,真正的威力在于空间分析。Geopandas集成了Shapely的几何运算能力。

7.1 空间关系判断

假设我们有两个GeoDataFrame:gdf_cities(点,城市)和gdf_provinces(面,省份)。

# 判断每个城市位于哪个省份内部 # 使用空间连接 cities_in_provinces = gpd.sjoin(gdf_cities, gdf_provinces, how=‘inner’, predicate=‘within’) # `predicate=‘within’` 表示“点在面内”的关系

sjoin是强大的空间连接函数,how参数类似Pandas的merge(‘left’, ‘right’, ‘inner’, ‘outer’),predicate参数定义空间关系,常见的有:

  • intersects:相交
  • within:在内部
  • contains:包含
  • touches:接触
  • crosses:穿过
  • overlaps:重叠

7.2 几何运算

对单个GeoDataFrame的几何列进行批量操作:

# 缓冲区分析:为每个城市点创建50公里的缓冲区 gdf_cities[‘buffer_zone’] = gdf_cities.to_crs(epsg=32650).geometry.buffer(50000) # 单位米 # 注意:先转换到投影坐标系! # 计算面积和周长 gdf_provinces[‘area_km2’] = gdf_provinces.to_crs(epsg=32650).geometry.area / 10**6 gdf_provinces[‘perimeter_km’] = gdf_provinces.to_crs(epsg=32650).geometry.length / 1000 # 简化几何图形 (Douglas-Peucker算法),减少数据量,用于快速可视化 gdf_provinces[‘geometry_simple’] = gdf_provinces.geometry.simplify(tolerance=0.01)

7.3 空间查询

# 找到所有与某个特定区域相交的要素 from shapely.geometry import box region_of_interest = box(115, 38, 117, 40) intersecting_features = gdf_provinces[gdf_provinces.intersects(region_of_interest)] # 找到距离某个点最近的两个要素 from shapely.geometry import Point target_point = Point(116.4, 39.9) # 计算距离 gdf_cities[‘dist_to_target’] = gdf_cities.geometry.distance(target_point) # 排序并获取最近的两个 nearest_two = gdf_cities.nsmallest(2, ‘dist_to_target’)

实操心得:进行空间连接时,如果数据量很大,性能会是个问题。在连接之前,确保两个数据集都设置了正确的CRS,并且如果可能,先进行初步的空间过滤(用bbox参数或.cx索引器)来减少数据量。此外,.sjoin操作会复制几何图形,导致结果文件变大,如果只需要属性关联,可以考虑使用.sjoin_nearest(最近邻连接)或先提取属性再合并。

8. 数据可视化:让地图说话

Geopandas内置了基于Matplotlib的简单绘图功能,非常适合快速检查数据和制作专题地图。

8.1 基础绘图

import matplotlib.pyplot as plt # 绘制几何图形 fig, ax = plt.subplots(figsize=(10, 8)) gdf_provinces.plot(ax=ax, color=‘lightgrey’, edgecolor=‘black’) gdf_cities.plot(ax=ax, color=‘red’, markersize=50, label=‘Cities’) plt.legend() plt.title(‘Provinces and Major Cities’) plt.show()

8.2 专题地图(Choropleth Map)

根据属性值着色是常见的需求。

fig, ax = plt.subplots(figsize=(12, 10)) # 根据‘population’字段绘制,使用‘YlOrRd’色带,图例显示 gdf_provinces.plot(column=‘population’, ax=ax, legend=True, legend_kwds={‘label’: “Population (millions)”, ‘orientation’: “horizontal”}, cmap=‘YlOrRd’, edgecolor=‘black’, linewidth=0.5) # 添加城市点 gdf_cities.plot(ax=ax, color=‘darkblue’, markersize=gdf_cities[‘pop’]/100, alpha=0.7) # 点大小与人口成比例 # 添加标注 for x, y, label in zip(gdf_cities.geometry.x, gdf_cities.geometry.y, gdf_cities[‘city’]): ax.text(x, y, label, fontsize=9, ha=‘center’, va=‘bottom’) plt.title(‘Population Distribution’) plt.axis(‘off’) # 关闭坐标轴 plt.tight_layout() plt.show()

8.3 使用Contextily添加底图

静态地图不够直观?可以添加在线瓦片底图。

import contextily as ctx # 确保数据是Web墨卡托坐标系 (EPSG:3857) gdf_provinces_web = gdf_provinces.to_crs(epsg=3857) gdf_cities_web = gdf_cities.to_crs(epsg=3857) fig, ax = plt.subplots(figsize=(15, 12)) gdf_provinces_web.plot(ax=ax, alpha=0.5, edgecolor=‘k’) gdf_cities_web.plot(ax=ax, color=‘red’, markersize=100) # 添加OpenStreetMap底图 ctx.add_basemap(ax, source=ctx.providers.OpenStreetMap.Mapnik) plt.axis(‘off’) plt.show()

注意contextily添加底图要求你的GeoDataFrame的CRS必须是EPSG:3857

踩坑记录:绘制时中文标签显示为方框。这是因为Matplotlib默认字体不包含中文。需要在绘图前设置中文字体:

plt.rcParams[‘font.sans-serif’] = [‘SimHei’] # 黑体 plt.rcParams[‘axes.unicode_minus’] = False # 解决负号显示问题

如果系统没有SimHei,可以指定其他已安装的中文字体路径。

9. 性能优化与大数据处理技巧

当处理城市级甚至国家级的精细几何数据时,GeoDataFrame可能会变得非常庞大,导致操作缓慢甚至内存不足。

9.1 核心优化策略

  1. 使用空间索引:Geopandas使用R-tree空间索引来加速空间查询。在读取数据后,空间索引通常是自动构建的。在进行sjoinintersects等操作时,确保索引有效。你可以通过gdf.sindex来访问空间索引对象。

  2. 投影优化:始终在投影坐标系下进行距离/面积计算。对于覆盖范围较大的数据,选择一个合适的投影(如UTM,阿尔伯斯等积投影)能减少变形,有时也能优化性能。

  3. 几何简化:对于可视化或不需要高精度的分析,使用geometry.simplify()方法简化几何图形,能极大减少数据量和计算负担。

    gdf_simple = gdf.copy() gdf_simple[‘geometry’] = gdf.geometry.simplify(tolerance=100) # 容差100米
  4. 选择性读取与切片:如前所述,利用bbox参数或先进行属性筛选,只读入需要的数据子集。

9.2 处理超大型数据集

对于无法一次性装入内存的数据,可以考虑以下方案:

  • 分块处理:如果数据在空间上可以分块(例如按省、按经纬度网格),可以写循环分批读取、处理、保存结果。

    import pandas as pd results = [] for chunk in pd.read_csv(‘huge_points.csv’, chunksize=100000): gdf_chunk = gpd.GeoDataFrame(chunk, geometry=gpd.points_from_xy(chunk.lon, chunk.lon)) # ... 处理chunk ... results.append(processed_chunk) final_gdf = gpd.GeoDataFrame(pd.concat(results, ignore_index=True))
  • 使用Dask-GeoPandasDask-GeoPandas将GeoDataFrame扩展到分布式计算,可以处理超过内存的数据。其接口与Geopandas高度相似。

    import dask_geopandas as dgpd dgdf = dgpd.read_file(‘very_large_shapefile.shp’) # 后续操作与geopandas类似,但计算是惰性的,需要调用.compute() result = dgdf.some_operation().compute()
  • 数据库方案:对于持久化、频繁查询的超大型空间数据,最好的归宿是空间数据库,如PostGIS(PostgreSQL扩展)或SpatiaLite(SQLite扩展)。你可以用Geopandas将数据导入这些数据库,利用其强大的空间索引和SQL查询能力,在需要时再将查询结果读回Geopandas进行分析或绘图。

个人体会:在最近一个全国路网分析项目中,原始Shapefile有数GB。我首先用QGIS(一款开源GIS软件)进行了预处理,按省级范围切分了数据。然后在Python脚本中循环处理每个省的文件,最后合并结果。这种“化整为零”的策略,比强行用一台普通电脑处理整个数据集要可行得多。对于真正的大数据,学习使用PostGIS是值得的投资。

10. 常见问题与故障排除实录

这里汇总了一些我踩过的坑和常见的错误,希望能帮你快速排雷。

问题现象可能原因解决方案
读取文件时报DriverErrorCPLE_OpenFailedError1. 文件路径错误或不存在。
2. Shapefile文件组不完整(缺少.shx, .dbf等)。
3. 文件被其他程序占用。
1. 检查路径,使用绝对路径或确保相对路径正确。
2. 确保同目录下有.shp, .shx, .dbf文件。
3. 关闭可能占用文件的GIS软件或编辑器。
中文或其他非英文字符显示为乱码.dbf文件的编码不是UTF-8,通常是GBK或GB2312。read_file时指定编码:gpd.read_file(‘file.shp’, encoding=‘GBK’)
to_crs()转换坐标时失败或报错1. 原始数据没有CRS (crsNone)。
2. 原始CRS定义错误或不标准。
1. 先用set_crs()定义正确的源CRS。
2. 尝试用gdf.estimate_utm_crs()自动估算,或查找数据源的官方CRS说明。
计算面积/长度时得到非常小或非常大的奇怪数值数据的地理坐标系(单位是度)下进行了计算。务必先转换到投影坐标系gdf_projected = gdf.to_crs(epsg=xxxx),然后在gdf_projected上计算。
空间连接 (sjoin) 速度极慢1. 数据量太大。
2. 没有利用空间索引。
1. 尝试先进行空间或属性筛选,减少数据量。
2. 确保两个GeoDataFrame都有有效的.sindex。对于极大文件,考虑使用Dask或数据库。
保存后图形在GIS软件中不显示或位置错误1. 保存时丢失了CRS信息。
2. 几何图形无效(如自相交的多边形)。
1. 保存前检查gdf.crs,确保不为None
2. 用gdf.geometry.is_valid检查几何有效性,用gdf.geometry.buffer(0)尝试修复一些无效图形。
AttributeError: ‘NoneType’ object has no attribute ‘startswith’通常发生在使用旧版依赖或环境混乱时,fionagdal库有问题。使用Conda重新创建一个干净的环境,并通过Conda-Forge安装所有包。这是最彻底的解决方法。
绘图时图形错位或变形绘图时多个图层的CRS不一致。确保所有要叠加绘制的GeoDataFrame(包括底图)都转换到同一个CRS(通常是EPSG:3857用于在线底图)。

最后,再分享一个调试小技巧:当你遇到奇怪的几何错误时,可以单独检查有问题的几何图形。shapely提供了is_validis_empty等属性,以及buffer(0)这种“修复”常见无效图形的方法。对于复杂的空间操作,有时将结果导出为GeoJSON或KML,在QGIS这类桌面软件中打开检查,会比在代码里埋头苦想更直观高效。

http://www.jsqmd.com/news/1306361/

相关文章:

  • 如何在浏览器中零代码编辑地理数据:geojson.io完全指南
  • 宁德房屋漏水怎么办?全城靠谱房屋修缮团队汇总,解决季节性渗漏难题 - 吉林同城获客
  • 减震器采购老手分享:GEO优化让技术方案变成获客入口 - 红枫叶GEO优化公司
  • FreeRTOS与LVGL在MH2457开发板上的嵌入式GUI系统移植与优化实战
  • 真正高效的职场人,早就不用书签办公了|一站式上班办公导航站详解
  • 豆包知识问答配置私密档案:内部泄露的8项未公开API权限策略与知识图谱注入规范
  • iOS越狱完全指南:5步解锁iPhone隐藏功能,从新手到高手
  • 雷达信号PRI变换法改进与电子战应用
  • 告别限速困扰:九大网盘直链下载助手的完整使用指南
  • 网盘直链下载助手:告别客户端,浏览器直接下载网盘文件的终极方案
  • 亚马逊申请部署5105颗卫星构建D2D网络,D2D产业前景广但仍处早期
  • ZenlessZoneZero-OneDragon终极指南:三步实现绝区零全自动游戏体验
  • 枣强县长途搬家公司推荐、单位搬迁公司哪家好?2026避坑指南:4个坑+5条硬标准 - mobible
  • ARM设备Docker实战:从安装到多架构镜像构建完整指南
  • PlayCover终极指南:在M芯片Mac上免费畅玩iOS游戏的完整教程
  • Fate/Grand Automata终极指南:告别FGO枯燥刷本,每天节省3小时游戏时间
  • DeepSeek-R详解
  • 深圳卖金避坑实战指南 拨开营销套路读懂公允计价规则 - 奢侈品回收评测
  • C# 13内联数组在Unity DOTS中的实战:零GC分配与极致性能优化
  • 离体肺数字孪生:从EVLP到多尺度模型,实现个体化疗效预测
  • 【OTFS通信】加法白高斯噪声AWGN信道模拟OTFS通信系统(含ISFFTSFFT和QAM BER与SNR来评估性能【含Matlab源码 15906期】含报告
  • 2026年沧州无缝弯头挑选 可关注河北广浩管件相关品类 - 奔跑123
  • 2026南山盐田搬家全解析:解决路径、适用场景与避坑指南,家顺兴搬家服务全解读 - 深圳家顺兴搬家
  • 知识变现迈入智能运营时代,探析创客匠人产品迭代路径与行业价值
  • 汇编语言入门:从Hello World到CPU指令执行原理
  • MultiButton:嵌入式按键处理的轻量级状态机框架详解
  • Qt QWebEngineView开发实战:避坑指南与最佳实践
  • akamai _sbsd
  • 滤芯过滤器AI获客心得:GEO优化让耗材生意获得持续询盘 - 红枫叶GEO优化公司
  • Steam创意工坊免费下载终极指南:WorkshopDL让跨平台玩家轻松获取模组