简介:本资源是武汉市路网矢量数据包,面向GIS开发、城市规划及交通分析等需要武汉市陆路交通与行政边界的ArcGIS用户。数据提供武汉市道路矢量图层、各行政区和武汉市边界图层,不含地铁、铁路、水路、航空,专注陆路路网,便于直接进行路网可视化、缓冲区分析或与人口、土地利用等数据叠加。包体共21个文件,以shp、dbf、prj、sbn、sbx、shx、xml等类型为主,shp为矢量主体,dbf存储属性信息,prj定义坐标系,sbn与sbx为空间索引,shx为几何索引,xml保存元数据,压缩包整体3.45MB,结构清晰便于按图层调用。目前已有2926人学习下载,适合需要快速获取武汉市基础路网底图的研究者或项目开发者,省去从零整理数据的繁琐过程,直接加载到ArcGIS中即可开展后续分析。
1. 一份能直接落地的武漢路網 shp:先回答三個使用前提
做城市道路分析,最耗時間的往往不是分析本身,而是找一張能直接信任的底圖。這份武漢市路網矢量數據 shp,就是把「找數據、下載、校準、清洗」這四步壓縮成「導入 ArcGIS 就能用」的資源——它表面上看只是一組線圖層,實際上決定了你後續做長度統計、緩衝區分析、路網密度計算時,結果到底能不能拿出去說明問題。
我在拆這類路網數據時會先確認三個前提:第一,shapefile 附屬文件是否完整,缺了 .prj 後續座標系全亂;第二,數據用的什麼座標基準,這直接影響跟影像底圖疊加時是否整體漂移;第三,屬性表裡有沒有可用的道路等級字段,沒有字段就只能畫圖,做不了統計。如果你是 GIS 課設、規劃前期選址、數據可視化 demo 的參與者,這份數據的性價比在於:它把「能不能用」的不確定性降到最低,剩下的是你自己要會的 ArcGIS 操作。
2. 導入與出圖:讓 shp 在 ArcGIS 里真正「能看」
2.1 從壓縮包到圖層:導入四步走
先明確一件事:shapefile 不是單個文件,而是至少三個文件組成的集合。.shp 存幾何、.dbf 存屬性、.shx 存索引,缺了任何一個,ArcGIS 要麼打不開,要麼屬性表一片空白。如果壓縮包裡還有 .prj 和 .cpg,那是最好的情況——前者記錄座標系,後者記錄屬性編碼。我拿到數據的第一步,永遠先列目錄確認這幾兄弟是否齊全:
import os from pathlib import Path data_dir = Path(r"D:\gis_data\wuhan_road") base_name = "road_network" exts = [".shp", ".shx", ".dbf", ".prj", ".cpg"] for ext in exts: f = data_dir / (base_name + ext) print(f.name, "->", "OK" if f.exists() else "MISSING")這段用於「驗屍」。base_name 必須和主文件實際名稱一致,比如實際叫 wuhan_road.shp,就寫 base_name = "wuhan_road";exts 列表裡 .cpg 缺失不一定致命,但往往伴隨屬性亂碼。打印結果若是 MISSING,先別往 ArcGIS 裡拖,補齊來源再繼續。
確認文件齊全後,導入本身沒有技術含量:打開 ArcCatalog,用「資料夾連接」指向解壓目錄,右鍵圖層預覽幾何和屬性,然後直接拖進 ArcMap。這裡有一個我反覆踩過的細節——目錄路徑不要帶中文,也不要放在桌面這種帶空格的位置。某些環境下 dbf 的編碼識別會被中文路徑干擾,表現為屬性表裡中文變亂碼,而文件本身其實是好的。把數據放到 D:\gis_data 這種純英文路徑下,是最廉價的排錯手段。
2.2 座標系統一:CGCS2000、WGS84 與 Web Mercator 的選擇
武漢市經度在 114°E 附近,國產地理數據最常見的座標基準是 CGCS2000,投影方式多為 3 度分帶高斯-克呂格投影,武漢落在第 38 帶,也就是中央經線為 114°E 的那一帶。但也有部分資源直接用 WGS84 經緯度存儲,加載時被 ArcGIS 當成未知座標系,或者被默認成 Web Mercator,於是疊底圖時整張路網平移幾百米甚至上千米。
判斷當前座標系,最穩的辦法是讓 ArcGIS 自己讀 .prj 文件並告訴你結果:
import arcpy arcpy.env.workspace = r"D:\gis_data\wuhan_road" sr = arcpy.Describe("road_network.shp").spatialReference print(sr.name) print("factoryCode:", sr.factoryCode) print("linearUnits:", sr.linearUnits)這一段的關鍵參數是 linearUnits——如果返回 Meter,說明是投影座標系,長度可以直接算;如果返回 Degree,說明是地理座標系,直接算長度是錯誤的。factoryCode 對應 EPSG 編號,但在國產數據裡有時返回 -1 或 0,表示 .prj 缺失或內容不標準,這種情況下需要手動定義投影。
定義投影和投影變換是兩件事。數據有幾何但缺座標系,用「Define Projection」補;數據有座標系但需要換到另一種,用「Project」工具。如果你的底圖是 Online 地圖(Web Mercator),路網是 CGCS2000 3 度帶,直接疊加會因橢球和投影差異產生偏移,常見做法是先把路網通過 Project 轉到 Web Mercator:
import arcpy arcpy.Project_management( in_dataset=r"D:\gis_data\wuhan_road\road_network.shp", out_dataset=r"D:\gis_data\wuhan_road\road_network_wm.shp", out_coor_system="PROJCS['WGS_1984_Web_Mercator_Auxiliary_Sphere'," "GEOGCS['GCS_WGS_1984',DATUM['D_WGS_1984'," "SPHEROID['WGS_1984',6378137.0,298.257223563]]," "PRIMEM['Greenwich',0.0],UNIT['Degree',0.0174532925199433]]," "UNIT['Meter',1.0]]", transform_method="")注意 out_coor_system 我直接寫了完整 WKT,避免依賴 ArcGIS 的座標系庫能否正確識別國產名稱。transform_method 在跨基準轉換時要填,CGCS2000 與 WGS84 差異很小,很多場景為了省事留空;但如果你手上的數據疊加後仍在影像上偏十幾米,就要補上七參數轉換,而不是靠手動平移硬湊。
2.3 出圖前必做的符號化:按道路等級渲染
導入和座標都正常後,第一個讓數據「像樣」的操作是符號化。路網數據最忌諱不分等級全畫成同一條細黑線——那既看不出城市骨架,也讓後續溝通過程變得非常糟糕。ArcGIS 裡的操作是雙擊圖層打開 Layer Properties,在 Symbology 分類中選擇 Categories > Unique values,Value Field 選擇道路等級字段,比如 CLASS 或 ROAD_LEVEL,再手動調整每類的線寬和顏色。
我通常用一套固定的配色思路:高速公路用橙色粗線,寬度 2.5 左右;主幹道用紅色,寬度 1.8;次幹道用黃色,寬度 1.2;支路用淺灰,寬度 0.8。這套規則不是什麼標準,但它貼合導航地圖的視覺習慣,開會投影時別人掃一眼就知道城市骨架在哪。
符號化前還要做一件事:查看等級字段到底有哪些值。有時候字段裡的類別是數字編碼,比如 1、2、3,需要對照圖層說明才能映射成主幹道、次幹道、支路。可以用屬性表的 Summarize 統計,也可以跑一句快速代碼:
import arcpy fc = r"D:\gis_data\wuhan_road\road_network.shp" with arcpy.da.SearchCursor(fc, ["CLASS"]) as cursor: values = set(row[0] for row in cursor) print(sorted(values))這裡使用 SearchCursor 遍歷全部要素的 CLASS 字段,集合去重後直接得到所有類別值。看到數字編碼時,別急著當成無效數據——先對照資源附帶的說明文件,找不到說明的,把數字類別和 NAME 字段結合起來看,比如 1 類路的名字大多是「某某大道」「某某高速」,基本能反推含義。
3. 屬性表拆解與清洗:字段決定了你能算什麼
3.1 一張路網 shp 的屬性表裡通常有哪些字段
路網矢量數據的屬性表,一半的價值在字段。不同來源的 shp 字段命名差異很大,但核心信息就那幾類。拿到表後先別急著統計,先看字段再動手。常見字段如下:
| 字段名 | 類型 | 常見含義 | 使用注意 |
|---|---|---|---|
| FID / OBJECTID | 長整型 | 要素唯一編號 | 不參與分析,但可作為關聯鍵 |
| NAME / RN_NAME | 字符串 | 道路名稱 | 可能為空,也可能多條道路同名 |
| CLASS / ROAD_LEVEL | 字符串或整型 | 道路等級 | 先確認是文本還是數字編碼 |
| ROAD_ID | 整型 | 道路邏輯編號 | 同一條路多段要素常共用一個 ID |
| SPEED | 整型 | 設計速度或限速 | 城市內有值,郊區可能大量為空 |
| WIDTH | 浮點型 | 道路紅線寬度 | 單位需確認是米還是公里 |
| SHAPE_LEN | 雙精度 | 幾何長度 | 依賴座標系,地理座標系下不可直接使用 |
這張表對應的是一個「能直接分析的理想情況」。實際拿到的數據可能有字段更少、命名不一致、或者把等級和名稱混在一個字段裡的情況,這很正常。我的經驗是:先確認 NAME 和 CLASS 兩個字段可用,其他字段是可選的加分項。NAME 用於抽樣驗證時對照真實地圖,CLASS 用於分級統計,缺了這兩個,數據的可用性要打對折。
3.2 空值、重複與斷頭線:清洗的三個重點
路網數據不是下載完就能直接算。第一類問題是空值:NAME 字段空著的要素,在分析時往往被忽略,但它們是真實存在的道路,忽略會讓長度偏小。第二類是重複:同一條道路被多次複製,或者不同要素共用同一個 ROAD_ID,統計時會重複計入。第三類是幾何層面的「斷頭」,線段端點沒有與其他線段連接,在後續網絡分析裡就是斷路。先用 Python 對屬性和重複做一次體檢:
import geopandas as gpd gdf = gpd.read_file(r"D:\gis_data\wuhan_road\road_network.shp") print("要素總數:", len(gdf)) print(gdf[["NAME", "CLASS"]].isnull().sum()) dup = gdf[gdf.duplicated(subset=["ROAD_ID"], keep=False)] print("有重複 ROAD_ID 的要素數:", len(dup)) invalid = gdf[~gdf.geometry.is_valid] print("幾何無效要素數:", len(invalid))這裡使用 geopandas 讀取 shp,isnull 統計字段空值,duplicated 按 ROAD_ID 查找重複,is_valid 檢查幾何是否自相交或退化。注意 duplicated 的 subset 參數要用你確認存在的字段,如果屬性表裡沒有 ROAD_ID,改用 NAME。幾何無效的要素一定要處理,它們在緩衝區和相交分析裡可能產生極端結果。
空值的處理我一般按場景區分:做總長度統計,空值要素保留但標記;做逐路統計,空值 NAME 的可以合併到「未命名道路」組。重複要素的處理是另一回事,不能直接刪——先看重複的 ROAD_ID 對應的幾何是否完全一致,如果幾何一致,是複製導致的重複,直接刪;如果幾何不一致,說明同一邏輯道路被拆成了多條,保留幾何。刪除重複要素時保留幾何完全一致的 FID 較小者,用 drop_duplicates 即可:
gdf2 = gdf.drop_duplicates(subset=["geometry"]) print("去重後要素數:", len(gdf2))在 geopandas 中對幾何列做去重可行,但要注意:float 精度可能讓「本該一致」的線段被判為不同。更穩的替代方案是先把幾何轉成 WKT 字符串再比對,但需要引入 shapely 的轉換,這裡用不上就不過度設計了。實際操作時我更多是確定重複模式後,回到 ArcGIS 用屬性表選中重複項,逐個看幾何位置來決定刪除與否。
3.3 統計道路總長度與分等級里程
有了乾淨的屬性和可信的座標系,統計才有意義。長度統計的前提是投影座標系,武漢數據用 CGCS2000 3 度帶或 UTM 50N 都可以,但不要用地理座標系,也不建議用 Web Mercator——後者在高緯度變形嚴重,統計出來的路網長度比真實值小不少。先轉到合適的投影,再算長度:
import geopandas as gpd gdf = gpd.read_file(r"D:\gis_data\wuhan_road\road_network_wm.shp") gdf = gdf.to_crs("EPSG:3857") # 僅作演示,正式統計不建議 gdf["length_km"] = gdf.geometry.length / 1000 summary = gdf.groupby("CLASS")["length_km"].agg(["sum", "mean", "count"]) print(summary.round(1))注意我在代碼裡標註了「正式統計不建議」——這行是演示如何把長度算出來,不是推薦做法。實際項目裡,如果原始數據就是 CGCS2000 3 度帶投影,直接在此座標系下算長度即可,不需要再轉。分組統計的關鍵是 groupby 的字段要和實際等級字段對上,CLASS 是字符串還是數字會影響分組結果的顯示順序。輸出三列:sum 是該等級總里程,mean 是平均每段長度,count 是路段數——這三個數字能幫你判斷數據是否合理,比如主幹道 count 只有幾十條,對一個大城市來說可能代表數據被過度合併了。
4. 避坑與排查:路網數據四個「一踩一個準」的雷
4.1 疊底圖時整張路網平移了幾百米
現象是路網線條能顯示,位置看起來也對,但和影像底圖疊加時整體往某個方向偏離,有時偏兩百米,有時偏一公里以上。原因幾乎都是座標系不統一:路網本身是 CGCS2000 或 WGS84 地理座標,ArcGIS 沒讀到 .prj,默認按 Web Mercator 顯示;或者路網是 CGCS2000 3 度帶,而你直接疊到了未設置投影的空白地圖上。解決辦法是先 Describe 確認座標系,缺失就用 Define Projection 補上正確的座標系,然後用 Project 轉到與底圖一致。不要手動移動圖層硬湊,那不是解決問題,只是把錯誤藏起來,後續分析全會被污染。
4.2 屬性表里的中文全是亂碼
現象是打開屬性表,NAME 字段顯示為「????」或一組無意義的字符。原因是 dbf 文件內部編碼與 ArcGIS 讀取時使用的編碼不一致,常見情況是數據用 UTF-8 存儲,而 ArcGIS 按 GBK 讀取,或者反過來。解決辦法分兩步:先看壓縮包裡有沒有 .cpg 文件,有就打開看裏面寫的是 UTF-8 還是 GBK;沒有就自己新建一個同名 .cpg 文件,內容寫UTF-8,放在 shp 同目錄下,重新加載。如果無效,用 QGIS 打開試試,它能自動識別更多編碼;在 QGIS 中導出時把編碼明確指定為 UTF-8,再回到 ArcGIS 加載,這是我在跨軟體協作時最常用的辦法。
4.3 道路在交叉口不交匯,緩衝區和密度分析質量很差
現象是做緩衝區時,相交道路各自出各的圈,互相不連通;做路網密度時,網格內道路長度明顯偏小。原因往往不是數據不準,而是路網是「雙線表達」或「未在節點處打斷」——兩條路在空間上相交,但幾何上沒有共享節點。解決辦法是在分析前先對路網執行「在交點處打斷線路」操作。ArcGIS Pro 中用 Geoprocessing 面板搜索「Planarize Lines」,ArcMap 中也可以用「Intersect」工具,把同一份路網自己和自己相交,輸出線要素,再把原數據的屬性連接回去。這一步是路網分析的地基,跳過它,後面所有基於連通性的分析都不可信。
4.4 全圖縮放卡成幻燈片
現象是加載後縮放到全圖範圍,軟體每動一下就轉圈,放大到局部反而流暢。原因是要素數量過多,且圖層沒有空間索引,或者索引過期。解決辦法是先做一次「重建空間索引」:在 ArcCatalog 裡選中圖層,在屬性裡找到 Index 標籤,重建空間索引。另一個容易被忽略的原因是符號化時給每個要素做了複雜的緩衝陰影效果,把符號化簡化成單一線條後再試。如果仍然卡,說明要素數到了幾十萬級別,此時要麼按行政區切割成多個圖層分區顯示,要麼轉成 File Geodatabase 的要素類來讀取,後者的讀取效率通常高於直接挂接 shp。
5. 從 shp 到分析結果:密度、緩衝區與中心線
5.1 路網密度計算:漁網與相交的組合拳
路網密度是城市分析裡出鏡率極高的指標,定義很簡單:單位面積內的道路總長度,單位是 km/km²。計算思路是先把研究區劃成規則網格,再統計每個網格內的道路長度。手動畫網格不可取,用 ArcGIS 的 Create Fishnet 工具生成 1km×1km 的漁網:
import arcpy arcpy.env.workspace = r"D:\gis_data\wuhan_road" arcpy.env.overwriteOutput = True arcpy.CreateFishnet_management( out_feature_class="grid_1km", origin_coord="438000 3331000", y_axis_coord="438000 3332000", cell_width=1000, cell_height=1000, number_rows="", number_columns="", labels="NO_LABELS", template="road_network.shp", geometry_type="POLYLINE" )CreateFishnet 的關鍵參數是 origin_coord 和 y_axis_coord,這兩個點決定了網格的起始位置和旋轉方向,必須和路網在同一座標系下,否則錯位。template 參數直接指定路網,它會讓網格範圍自動貼合路網的範圍,省去手動調整的麻煩。geometry_type 這裡用 POLYLINE,輸出網格邊界線,也可以改成 POLYGON 輸出網格面,看你下一步怎麼用。
網格建立後,把路網和網格做相交,讓每一段道路都被打上它所在網格的編號:
arcpy.analysis.Intersect( in_features=[["road_network.shp", ""], ["grid_1km", ""]], out_feature_class="road_grid_intersect", join_attributes="ALL", output_type="LINE" )Intersect 輸出的線段會帶上兩邊的全部屬性,其中網格面的 FID 就是網格編號。接著用 Summary Statistics 按網格編號統計道路長度的總和,再跟網格面積換算成密度。這一步最隱蔽的問題是網格邊界上的道路被切分後,長度精度取決於 Intersect 是否在切割點處光滑處理,一般不用過度擔心,因為 1km 網格切分導致的誤差遠小於數據本身的採集誤差。
5.2 道路緩衝區與城市覆蓋率
緩衝區是路網數據應用的第二個常見場景。它回答的問題是:城市道路兩側多少範圍內是「可達區域」。不同等級道路對出行的重要性不同,緩衝距離也要不同——這是我特別強調屬性字段價值的地方。沒有 CLASS 字段,你只能全路網統一做 500m 緩衝,結果粗糙得多。
import arcpy arcpy.env.workspace = r"D:\gis_data\wuhan_road" buffers = [] for cls, dist in [("1", 800), ("2", 500), ("3", 300), ("4", 150)]: out_fc = f"buf_{cls}" arcpy.analysis.Buffer( in_features="road_network.shp", out_feature_class=out_fc, buffer_distance_or_field=dist, dissolve_option="ALL" ) buffers.append(out_fc) arcpy.management.Merge(buffers, "buffer_all")這里的核心是把按等級的緩衝結果合併成一個圖層。dissolve_option=「ALL」讓同一等級內的重疊緩衝區融成一體,避免面積重複計算。距離參數 800/500/300/150 是經驗值,不是標準——如果你做的是 15 分鐘生活圈,距離要縮小;做的是全市道路影響評估,就放大。合併後用幾何面積減去水域等不可達區域,就能算出道路緩衝區覆蓋率。這個指標常用於評價城市服務均衡性,但它對路網的連通性極度敏感,如果沒做第 4.3 節的節點打斷,結果會略偏小。
5.3 中心線提取與線路簡化
很多路網數據為了表現道路寬度,用雙線或面狀表達,這在可視化上好看,但做網絡分析時必須得到單線中心線。ArcGIS 提供 Collapse Dual Lines To Centerline 工具,專門處理雙線道路的塌縮問題,輸入雙線要素,輸出中間的軸線。參數裡有一個 Maximum Width 的選項,表示雙線之間最大距離,超過這個距離的雙線不會被塌縮——這個值要根據數據實際情況調整,城市主幹道的雙線間距往往大於支路,設太小會漏掉主幹道。
中心線提取完成後,下一步是簡化。原始路網的節點往往過密,用來做緩衝區沒問題,但用來出小比例尺圖件或發布 Web 服務,會讓文件體積和渲染時間膨脹。Simplify Line 工具基於 Douglas-Peucker 算法,容差設置 5 米到 20 米比較常見。武漢市中心城區道路轉彎密集,容差 5 米幾乎不丟形狀;遠城區快速路線形平緩,容差可以放到 10 米以上。容差太小的簡化沒有意義,容差太大則會把匝道、環島的形狀抹平,出圖後被熟悉城市的人一眼看出問題。我一般在簡化前後各算一次總長度,簡化後的長度偏差控制在 2% 以內才認為可接受。
6. 用一個笨辦法驗證路網質量:抽樣對比
6.1 隨機抽二十條路,逐條和地圖底圖對
幾何和屬性都處理完了,最後一步是驗證。驗證不需要高深算法,最可靠的辦法是抽樣對比。用 Python 從路網中隨機抽 20 條要素,導出為單獨圖層,加載到地圖裡疊在影像底圖上,逐條核對起終點、走向、位置偏差:
import geopandas as gpd import random gdf = gpd.read_file(r"D:\gis_data\wuhan_road\road_network.shp") sample = gdf.sample(n=20, random_state=42) sample["name"] = sample["NAME"].fillna("未命名") sample[["name", "geometry"]].to_file(r"D:\gis_data\wuhan_road\check_sample.shp")random_state 固定隨機種子,保證每一次驗證抽到的樣本一致,方便復盤和別人復現。檢查重點有三項:道路是否存在於影像底圖上、走向是否一致、偏移是否在合理範圍。有一條對不上,先別急著下結論說數據有問題——可能是數據時效性導致新建道路和拆除道路的差異,這種差異在城市擴張區域非常常見。
6.2 用交叉口數量做一次快速交叉檢查
逐條對比的成本較高,想更快,可以統計路網節點數和交叉口數做合理性判斷。路網相交節點數量級與道路總長度之間存在經驗比例關係,一般城市的路網,節點數大致是道路要素數的 1.2 到 1.8 倍。如果相交後發現節點數比要素數量還少,說明大量道路相互斷開,連通性有問題;如果節點數是要素數的幾倍,說明道路被切得過碎,源數據質量堪憂。這個比例不是嚴格標準,但它能快速暴露數據結構的異常。
那次我拿到一份路網,沒做任何驗證就投入到項目分析裡,匯報時被問到「這條路為什麼穿過了水體」,我才發現數據和水系沒有做任何空間一致性檢查。從那以後,我每次拿到路網 shp,都強制走一遍「隨機抽樣 + 底圖對比 + 節點比例檢查」三道工序,成本不高,但能擋住九成以上的低級錯誤。希望這些路徑對你有用。
本文还有配套的精品资源,点击获取