
简介本资源为面向GIS开发者、城市规划研究者及地理信息专业学生的深圳市2020年多源POI综合数据集支撑城市空间分析、商业选址、地形建模与公共服务评估等实际应用。压缩包共137个文件含15组shp/shx/prj/cpg/sbn/sbx等矢量配套文件支持QGIS/ArcGIS直接加载、14个xlsx格式POI表格含科技文化、餐饮、医疗保障、风景名胜等10类详细分类以及1个30米分辨率DEMtiftfwovr和完整行政区划矢量数据整体容量54.04MB。已有747人学习下载数据结构规范、字段语义明确可直接用于POI热力图生成、坡度坡向计算、行政边界叠加分析及Excel与GIS平台协同处理。用户无需额外清洗即可开展空间统计、服务设施覆盖率评估或区域功能识别等进阶分析任务。1. 深圳市2020年POI数据集不是“拿来就能用”的地理底图而是30M DEM多源POI行政区划的混合体适合做城市空间分析但必须先过三道清洗关你下载完那个标着“深圳市2020年POI数据集包含30M分辨率DEM、行政区划、shp格式POI、excel格式POI数据.7z”的压缩包双击解压——结果发现shp文件打不开缺.prjExcel里地址字段全是“南山区科技园某大厦A座”DEM栅格值全为-9999行政区划面边界在QGIS里显示错位……这不是数据质量问题而是典型的城市地理数据混合包陷阱它把四类异构数据硬塞进一个压缩包却没告诉你它们坐标系不统一、时间戳不一致、语义标准不兼容。这个数据集真正价值不在“开箱即用”而在于它提供了深圳2020年尺度下地形起伏30M DEM、行政骨架区/街道/社区三级边界、实体锚点shp与excel双源POI的原始切片。适合做商圈热力建模、设施可达性评估、或作为深度学习模型的空间先验输入但前提是——你得亲手把这堆“地理零件”拧成一套能跑通的流水线。新手容易卡在坐标系对齐上老手常栽在POI去重逻辑里。本文就带你从解压开始一环扣一环地把这套数据变成可计算、可验证、可复用的本地地理数据库。2. 解压与初筛识别四类数据的真实结构与隐含约束这个.7z包表面是“一套数据”实则是四个独立子系统拼装而成。直接解压后你会看到类似这样的目录结构Shenzhen_2020_POI/ ├── DEM_30m/ │ ├── shenzhen_dem.tif │ └── readme_dem.txt ├── Boundaries/ │ ├── shenzhen_district.shp │ ├── shenzhen_subdistrict.shp │ └── shenzhen_community.shp ├── POI_SHP/ │ ├── poi_all.shp │ └── poi_metadata.csv └── POI_EXCEL/ ├── poi_raw.xlsx └── poi_field_mapping.xlsx注意不要跳过readme_dem.txt和poi_metadata.csv——它们藏着关键约束。比如readme_dem.txt里明确写着“DEM采用CGCS2000 / 3-degree Gauss-Kruger zone 38EPSG:4547高程单位米无效值-9999”而poi_metadata.csv则记录了shp版POI的字段定义“name_en字段为空率62%type_code采用GB/T 23705-2009二级分类编码”。这些不是废话是后续所有操作的校验基准。2.1 用gdalinfo确认DEM元数据30M分辨率≠30米精度很多用户看到“30M分辨率”就默认是30米网格但实际需验证gdalinfo Shenzhen_2020_POI/DEM_30m/shenzhen_dem.tif输出关键段Size is 4217, 3124 Coordinate System is: PROJCRS[CGCS2000 / 3-degree Gauss-Kruger zone 38, BASEGEOGCRS[CGCS2000, DATUM[China Geodetic Coordinate System 2000, ELLIPSOID[CGCS2000,6378137,298.257222101, LENGTHUNIT[metre,1]]], PRIMEM[Greenwich,0, ANGLEUNIT[degree,0.0174532925199433]]], CONVERSION[3-degree Gauss-Kruger zone 38, METHOD[Transverse Mercator, ID[EPSG,9807]], PARAMETER[Latitude of natural origin,0, ANGLEUNIT[degree,0.0174532925199433], ID[EPSG,8801]], PARAMETER[Longitude of natural origin,114, ANGLEUNIT[degree,0.0174532925199433], ID[EPSG,8802]], PARAMETER[Scale factor at natural origin,1, SCALEUNIT[unity,1], ID[EPSG,8805]], PARAMETER[False easting,38500000, LENGTHUNIT[metre,1], ID[EPSG,8806]], PARAMETER[False northing,0, LENGTHUNIT[metre,1], ID[EPSG,8807]]], CS[Cartesian,2], AXIS[easting (X),east, ORDER[1], LENGTHUNIT[metre,1]], AXIS[northing (Y),north, ORDER[2], LENGTHUNIT[metre,1]]] Origin (38499999.99999999,2800000.00000000) Pixel Size (30.000000000000000,30.000000000000000)✅ 验证通过确实是EPSG:4547坐标系像素尺寸30×30米Origin起始坐标符合深圳西部边界。⚠️ 注意Origin (38499999.99999999,2800000.00000000)是高斯投影的平面坐标不是WGS84经纬度——后续叠加POI时必须统一到此坐标系而非简单转WGS84。2.2 用ogrinfo检查SHP矢量完整性缺.prj不是最大风险字段类型错才是shp文件夹里看似只有.shp但实际需要配套的.dbf、.shx、.prj。用ogrinfo快速诊断ogrinfo -so Shenzhen_2020_POI/POI_SHP/poi_all.shp重点看两行Layer name: poi_all Geometry: Point Feature Count: 1248761 Extent: (113.782345, 22.448921) - (114.623102, 22.856719) Layer SRS WKT: GEOGCRS[WGS 84, DATUM[World Geodetic System 1984, ELLIPSOID[WGS 84,6378137,298.257223563, LENGTHUNIT[metre,1]]], PRIMEM[Greenwich,0, ANGLEUNIT[degree,0.0174532925199433]], CS[ellipsoidal,2], AXIS[geodetic latitude (Lat),north, ORDER[1], ANGLEUNIT[degree,0.0174532925199433]], AXIS[geodetic longitude (Lon),east, ORDER[2], ANGLEUNIT[degree,0.0174532925199433]]]❌ 问题暴露POI_SHP用的是WGS84EPSG:4326而DEM用的是CGCS2000 / Gauss-KrugerEPSG:4547。二者坐标系不同直接叠加会导致偏移达300米以上因CGCS2000与WGS84在华南区域存在厘米级差异但投影变换会放大误差。✅ 补救必须将POI_SHP重投影到EPSG:4547而非简单“设置坐标系”。ogr2ogr命令如下ogr2ogr -t_srs EPSG:4547 \ -s_srs EPSG:4326 \ -f ESRI Shapefile \ poi_all_4547.shp \ Shenzhen_2020_POI/POI_SHP/poi_all.shp提示-s_srs指定源坐标系-t_srs指定目标坐标系顺序不能颠倒。若漏写-s_srsogr2ogr会尝试自动识别但在WGS84无.prj文件时极易误判为CGCS2000导致重投影失败。2.3 Excel POI的字段陷阱地址文本标准化比坐标补全更耗时poi_raw.xlsx打开后典型结构如下idnameaddresstype_codelnglat1001腾讯大厦广东省深圳市南山区科技园中二路2号120101113.934222.53211002华为坂田基地深圳市龙岗区坂雪岗大道120102114.128722.6543表面看lng/lat齐全但实测发现address列存在大量“深圳市南山区”重复前缀导致地址相似度计算失真type_code虽标称GB/T 23705-2009但实际混入了旧版编码如120101应为“综合办公楼”但部分记录写成1201lng/lat有12.7%记录落在深圳行政范围外经st_within验证属GPS漂移或人工录入错误。因此Excel POI不能直接导入GIS必须先做三件事清洗address用正则re.sub(r^[^\u4e00-\u9fa5]*?[\u4e00-\u9fa5]?[省市区县镇], , address)剥离省级前缀校验type_code加载GB/T 23705-2009标准码表将3位码补零为6位1201→001201再映射到标准二级类目空间过滤用geopandas.read_file(shenzhen_district.shp).unary_union生成深圳多边形保留gpd.points_from_xy(df.lng, df.lat).within(shenzhen_polygon)为True的记录。3. 坐标系统一CGCS2000与WGS84的毫米级差异如何影响城市级分析深圳POI数据集最隐蔽的坑不是文件损坏而是坐标系混用引发的系统性偏移。你以为只是“换个投影”实际是在处理中国大地坐标系CGCS2000与全球坐标系WGS84的物理基准差异。这种差异在深圳城区表现为平均偏移约0.05~0.15米单点可忽略但当你要做“地铁站500米服务半径覆盖分析”时0.1米偏移乘以10万POI会导致覆盖统计误差超3%——足够让一份商业选址报告被客户质疑。3.1 为什么不能直接用EPSG:4490CGCS2000地理坐标系替代EPSG:4326网上常见做法是把WGS84 POI“强行设为”CGCS2000地理坐标系EPSG:4490理由是“两者都是地心坐标系差别可忽略”。这是危险的简化。真实情况是对比项WGS84 (EPSG:4326)CGCS2000 (EPSG:4490)深圳实测偏移参考椭球WGS84椭球a6378137, f1/298.257223563CGCS2000椭球a6378137, f1/298.257222101椭球扁率差导致高程偏差0.1mm平面影响0.01m大地基准GPS观测网平差结果全国2500个GNSS连续运行基准站平差结果平面位置差异0.05~0.15m华南区域投影方式无地理坐标系高斯-克吕格3度带深圳用38带投影变形导致同一经纬度在EPSG:4547下xy值与WGS84直投差300m关键结论WGS84与CGCS2000的地理坐标系EPSG:4326 vs EPSG:4490差异极小但一旦进入投影坐标系如EPSG:4547必须经过严格转换不能仅靠坐标系赋值。3.2 正确的POI重投影流水线从WGS84到CGCS2000高斯投影的三步法以poi_all.shp为例正确流程是import geopandas as gpd from pyproj import CRS # Step 1: 读取原始shp自动识别为EPSG:4326 gdf gpd.read_file(poi_all.shp) # Step 2: 显式声明源坐标系防自动识别失效 gdf.crs CRS.from_epsg(4326) # Step 3: 使用pyproj.Transformer进行基准转换投影变换非简单重投影 transformer pyproj.Transformer.from_crs( crs_fromCRS.from_epsg(4326), crs_toCRS.from_epsg(4547), always_xyTrue # 保证x,y顺序经度,纬度→东坐标,北坐标 ) # 执行转换关键调用transform非to_crs gdf_4547 gdf.copy() gdf_4547.geometry gdf_4547.geometry.to_crs(CRS.from_epsg(4547)) # 注geopandas 0.12已内置基准转换但需确保pyproj3.0.0且安装epsg数据库 gdf_4547.to_file(poi_all_4547.shp, driverESRI Shapefile)注意gdf.to_crs(CRS.from_epsg(4547))在新版本geopandas中已自动调用pyproj的基准转换但必须验证转换后坐标是否落入深圳范围。验证代码bounds gdf_4547.total_bounds # 应接近 [38499999, 2800000, 38626500, 2893720] print(fX范围: {bounds[0]:.0f} ~ {bounds[2]:.0f}) # 若出现38xxx000说明成功若为113~114说明仍为经纬度3.3 DEM与POI叠加验证用Zonal Statistics反向检验投影精度重投影后的POI能否与DEM精准套合最可靠方法不是目视而是用栅格统计验证import rasterio from rasterio.mask import mask import numpy as np # 读取DEM with rasterio.open(shenzhen_dem.tif) as src: # 创建一个100m缓冲区的圆形mask模拟POI服务半径 poi_geom gdf_4547.iloc[0].geometry.buffer(100) # 单位米因坐标系为EPSG:4547 out_image, out_transform mask(src, [poi_geom.__geo_interface__], cropTrue) # 提取高程均值 valid_data out_image[0][out_image[0] ! src.nodata] print(f腾讯大厦100m内平均高程: {np.mean(valid_data):.2f} m)✅ 若输出高程值在45~55m之间腾讯大厦实际海拔约48m说明POI点位与DEM栅格精准对齐❌ 若输出nan或高程值异常如-9999或200m说明POI坐标仍在WGS84经纬度未完成投影转换。4. POI数据融合shp与Excel双源去重的3种策略及适用场景数据集同时提供shp版POI124万条和Excel版POI89万条但二者并非子集关系——shp含大量政府设施派出所、社区工作站Excel含大量商业网点奶茶店、快递柜。直接合并会引入重复记录如“深圳湾体育中心”在shp中为polygon在Excel中为point必须设计融合策略。4.1 基于空间位置的硬去重适用于同一实体的多源采集核心逻辑若两个POI的几何中心距离 50米且name相似度 0.8则视为同一实体。使用geopandas difflib实现from difflib import SequenceMatcher import shapely.ops as so def similarity(a, b): return SequenceMatcher(None, a, b).ratio() # 合并shp与excel为统一GeoDataFrame gdf_shp gpd.read_file(poi_all_4547.shp) gdf_excel gpd.read_file(poi_excel_4547.shp) # Excel已转为shp并重投影 gdf_combined pd.concat([gdf_shp, gdf_excel], ignore_indexTrue) # 构建空间索引加速查询 gdf_combined.sindex duplicates [] for idx, row in gdf_combined.iterrows(): # 查找50米内其他POI possible_matches gdf_combined.iloc[ list(gdf_combined.sindex.intersection(row.geometry.buffer(50).bounds)) ] for _, match in possible_matches.iterrows(): if idx match.name or match.name in duplicates: continue # 计算名称相似度仅比对中文字符 name_a re.sub(r[^\u4e00-\u9fa5], , str(row[name])) name_b re.sub(r[^\u4e00-\u9fa5], , str(match[name])) if len(name_a) 2 and len(name_b) 2 and similarity(name_a, name_b) 0.8: duplicates.append(match.name) break gdf_dedup gdf_combined.drop(duplicates).reset_index(dropTrue)✅ 优势物理位置准适合设施类POI医院、学校❌ 劣势对“连锁店”误杀如10家喜茶门店名相同但位置不同会被删剩1家。4.2 基于业务规则的软融合保留差异化属性解决“同名不同质”针对连锁品牌改用属性融合策略保留所有POI点位将shp中的admin_level行政等级与Excel中的business_hours营业时间合并到同一记录新增source_flag字段标记来源shp_gov / excel_commercial。# 以nameaddress为联合键merge时保留所有字段 gdf_shp[join_key] gdf_shp[name].str.replace(r[^\w\u4e00-\u9fa5], ) _ \ gdf_shp[address].str.replace(r[^\w\u4e00-\u9fa5], ) gdf_excel[join_key] gdf_excel[name].str.replace(r[^\w\u4e00-\u9fa5], ) _ \ gdf_excel[address].str.replace(r[^\w\u4e00-\u9fa5], ) gdf_fused gdf_shp.merge( gdf_excel.drop(columns[geometry]), onjoin_key, howouter, suffixes(_shp, _excel) ) # 用coalesce逻辑填充字段 gdf_fused[type_code] gdf_fused[type_code_shp].fillna(gdf_fused[type_code_excel]) gdf_fused[business_hours] gdf_fused[business_hours_excel] gdf_fused[admin_level] gdf_fused[admin_level_shp]✅ 优势保留商业多样性支持“同一品牌不同业态”分析如喜茶门店vs喜茶实验室❌ 劣势需人工校验join_key生成逻辑地址清洗质量决定融合效果。4.3 基于时空可信度的加权融合当2020年数据中混入历史记录检查Excel元数据发现poi_raw.xlsx中update_date字段有2018、2019、2020三个年份而shp版标注为“2020年普查成果”。此时应按时间可信度加权数据源时间权威性推荐权重处理方式shp版政府普查★★★★★1.0作为主表update_date强制设为2020-12-31Excel版商业爬取★★☆☆☆0.6仅当shp中无对应记录时才插入且source_confidence0.6# 优先保留shp数据Excel仅作补充 gdf_master gdf_shp.copy() gdf_master[source_confidence] 1.0 # 对Excel中shp不存在的记录追加到master excel_only gdf_excel[~gdf_excel[join_key].isin(gdf_shp[join_key])] excel_only[source_confidence] 0.6 gdf_final pd.concat([gdf_master, excel_only], ignore_indexTrue)提示source_confidence字段将在后续空间分析中用于加权热力图如weightsource_confidence*visit_frequency避免低质量数据拉低模型精度。5. 避坑指南深圳POI数据集的5个血泪经验与现场排查方案这个数据集最大的特点是“表面规整内里复杂”。以下是我用该数据集支撑3个商业项目踩出的坑每一条都附带现象、根因和可执行解决方案拒绝玄学排错。5.1 现象QGIS中加载shenzhen_dem.tif后显示全黑拉伸后仍是灰蒙蒙一片原因DEM栅格的NoData值-9999未被正确识别QGIS默认将-9999渲染为黑色而非透明。解决在QGIS中右键DEM图层 → Properties → Symbology → Band rendering → 将No data value手动填入-9999或用gdal_translate预处理gdal_translate -a_nodata -9999 shenzhen_dem.tif dem_fixed.tif5.2 现象用geopandas读取poi_all.shp时报错TopologyException: Input geom 0 is invalid原因shp中存在自相交多边形如某些“公园”面要素而geopandas 0.10默认开启拓扑验证。解决# 方案1读取时跳过验证快速修复 gdf gpd.read_file(poi_all.shp, keep_nansFalse) # 方案2修复几何彻底解决 gdf.geometry gdf.geometry.buffer(0) # 0缓冲可修复多数自相交 gdf gdf[gdf.is_valid] # 过滤仍无效的记录5.3 现象Excel POI导出为shp后中文字段全部变成乱码原因Excel保存为CSV时默认UTF-8 with BOM而ogr2ogr读取时误判为GBK。解决用Notepad将poi_raw.xlsx另存为CSVUTF-8无BOM或强制指定编码ogr2ogr -f ESRI Shapefile -lco ENCODINGUTF-8 poi_excel.shp poi_raw.csv5.4 现象行政区划shp中“南山区”面要素与POI点位明显错位偏移约2km原因shenzhen_district.shp使用的是CGCS2000地理坐标系EPSG:4490但被错误加载为WGS84EPSG:4326。解决在QGIS中右键图层 →Set Layer CRS→ 选择EPSG:4490非EPSG:4326在代码中显式声明crsgdf_district gpd.read_file(shenzhen_district.shp) gdf_district.crs EPSG:4490 # 强制赋值 gdf_district gdf_district.to_crs(EPSG:4547) # 再转投影5.5 现象用gdf.to_file()导出融合后POI时type_code字段从数字变成科学计数法1.2e05原因pandas将长整型自动转为float64导出shp时丢失精度。解决# 导出前强制转为字符串保持编码原样 gdf_final[type_code] gdf_final[type_code].astype(str).str.zfill(6) # 或转为int64需确保无nan gdf_final[type_code] gdf_final[type_code].fillna(0).astype(int64)6. 进阶技巧用DEM高程约束POI语义构建“地形感知型”城市分析模型做完数据清洗和融合你手上已有深圳2020年最完整的POI底图。但真正拉开差距的是把30M DEM从背景图变成分析变量。我曾用这个组合解决过一个真实需求某连锁咖啡品牌想在南山科技园选新店址要求“步行5分钟可达、避开陡坡、靠近地铁口”。传统方法只算直线距离而我们加入了高程约束——因为深圳南山多丘陵500米直线距离可能要爬30米高差实际步行耗时翻倍。6.1 从DEM提取坡度与坡向量化“步行友好度”import numpy as np from osgeo import gdal, gdalconst def calc_slope_aspect(dem_path, slope_path, aspect_path): 用GDAL计算坡度度与坡向0~360 dem gdal.Open(dem_path, gdalconst.GA_ReadOnly) band dem.GetRasterBand(1) xsize, ysize band.XSize, band.YSize # 获取地理变换参数 geotrans dem.GetGeoTransform() pixel_width geotrans[1] pixel_height abs(geotrans[5]) # 读取DEM数组 dem_array band.ReadAsArray() # 计算坡度Horn算法 # dx (z[i,j1] - z[i,j-1]) / (2*dx) # dy (z[i1,j] - z[i-1,j]) / (2*dy) dx np.gradient(dem_array, axis1) / pixel_width dy np.gradient(dem_array, axis0) / pixel_height slope_rad np.arctan(np.sqrt(dx**2 dy**2)) slope_deg np.degrees(slope_rad) # 计算坡向 aspect_rad np.arctan2(-dx, dy) # 注意arctan2(y,x)此处y-dx, xdy aspect_deg np.degrees(aspect_rad) % 360 # 保存为tif driver gdal.GetDriverByName(GTiff) slope_ds driver.Create(slope_path, xsize, ysize, 1, gdal.GDT_Float32) slope_ds.SetGeoTransform(geotrans) slope_ds.SetProjection(dem.GetProjection()) slope_ds.GetRasterBand(1).WriteArray(slope_deg) aspect_ds driver.Create(aspect_path, xsize, ysize, 1, gdal.GDT_Float32) aspect_ds.SetGeoTransform(geotrans) aspect_ds.SetProjection(dem.GetProjection()) aspect_ds.GetRasterBand(1).WriteArray(aspect_deg) calc_slope_aspect( shenzhen_dem.tif, shenzhen_slope.tif, shenzhen_aspect.tif )✅ 输出shenzhen_slope.tif值域0~45°15°视为“陡坡”✅ 输出shenzhen_aspect.tif值域0~360°0°正北90°正东可用于分析“阳光照射面”。6.2 构建步行阻力模型把高程、坡度、道路等级合成一张阻力栅格单纯看坡度不够——深圳有大量“之字形”盘山路坡度不高但绕行距离长。我们用OpenStreetMap道路数据另行下载与DEM叠加生成综合阻力道路类型基础阻力系数坡度修正系数slope5°时最终阻力地铁口500m缓冲区0.1×1.00.1主干道双向4车道0.3×(10.05×slope)max(0.3, 0.30.05×slope)社区支路0.8×(10.15×slope)max(0.8, 0.80.15×slope)人行步道0.5×(10.1×slope)max(0.5, 0.50.1×slope)# 示例对主干道栅格应用坡度修正 road_main rasterio.open(road_main.tif).read(1) # 值为1是主干道或0 slope rasterio.open(shenzhen_slope.tif).read(1) resistance_main np.where( road_main 1, np.maximum(0.3, 0.3 0.05 * slope), 0 )最终用rasterio.merge.merge()将各类阻力栅格叠加得到一张0~5的综合阻力图。再用scipy.ndimage.distance_transform_edt()计算每个POI到地铁口的加权欧氏距离非直线距离筛选出阻力值1.2且距离800的候选点——这才是真正的“步行友好”。6.3 用POI密度反推DEM精度发现数据集隐藏的质检线索最后分享一个反向技巧用POI分布验证DEM质量。原理是——真实城市中POI密度与地形强相关海拔20~50m的缓坡地带如南山科技园POI密度最高海拔100m的山地区域如梧桐山POI密度趋近于0海拔5m的滨海区如前海因填海造地POI应沿新修道路密集分布。我们计算每个30×30米DEM像元内的POI数量绘制散点图import matplotlib.pyplot as plt # 将POI点栅格化为密度图30m分辨率 from rasterio.features import rasterize shapes [(geom, 1) for geom in gdf_final.geometry] density rasterize( shapes, out_shape(3124, 4217), # 与DEM一致 transformsrc.transform, fill0, merge_algrasterio.enums.MergeAlg.add ) # 提取DEM高程与POI密度对应关系 elevations dem_array.flatten() densities density.flatten() valid_mask (elevations 0) (elevations 1000) (densities 0) elev_valid elevations[valid_mask] den_valid densities[valid_mask] plt.scatter(elev_valid, den_valid, s0.1, alpha0.3) plt.xlabel(Elevation (m)) plt.ylabel(POI Density (count per 900m²)) plt.title(POI Density vs Elevation: Expected peak at 20-50m) plt.show()✅ 若曲线在20~50m区间出现明显峰值说明DEM与POI空间匹配良好❌ 若峰值出现在0~5m滨海区或完全平坦无峰值则提示DEM存在系统性高程偏移需重新校准。这就是我用深圳市2020年POI数据集跑通的第一个商业项目——没有炫技的AI模型只有扎实的坐标系对齐、严谨的坡度计算、以及用POI密度反向验证DEM的土办法。后来客户说“你们的选址建议比我们自己画本文还有配套的精品资源点击获取