強大的GeoPandas,幾行代碼實現點轉線功能
在GIS數據處理操作時,經常會用到點轉線操作。一般ArcGIS、QGIS等等都會提供相應的工具。
這裏提供一種利用Python實現點轉線的方法。
1、原料 Pandas、GeoPandas、Shapely
Pandas及GeoPandas的強大之處,誰用誰知道
先來看以下點文件,格式是帶經緯度座標的csv文件。我們先用pandas將數據呈現出來。內容如下:
import pandas as pd
import geopandas as gpd
from shapely.geometry import LineString,Point
fp = r'E:\Dev\data\BigRoads31.csv'
df = pd.read_csv(fp)
df
FID | Name | State | Speed | Num | Lng | Lat | |
---|---|---|---|---|---|---|---|
0 | 0 | 科技六路 | 3 | 10.0 | 0 | 108.888107 | 34.211662 |
1 | 1 | 科技六路 | 3 | 10.0 | 0 | 108.889725 | 34.211670 |
2 | 2 | 瞪羚路 | 2 | 15.0 | 1 | 108.856926 | 34.201595 |
3 | 3 | 瞪羚路 | 2 | 15.0 | 1 | 108.857033 | 34.201599 |
4 | 4 | 瞪羚路 | 2 | 15.0 | 1 | 108.859413 | 34.201637 |
5 | 5 | 瞪羚路 | 2 | 15.0 | 1 | 108.861893 | 34.201626 |
6 | 6 | 瞪羚路 | 2 | 15.0 | 1 | 108.863655 | 34.201611 |
7 | 7 | 瞪羚路 | 2 | 15.0 | 1 | 108.868385 | 34.201630 |
8 | 8 | 瞪羚路 | 2 | 15.0 | 1 | 108.869408 | 34.201630 |
9 | 9 | 瞪羚路 | 2 | 25.0 | 2 | 108.869408 | 34.201710 |
10 | 10 | 瞪羚路 | 2 | 25.0 | 2 | 108.869308 | 34.201710 |
11 | 11 | 瞪羚路 | 2 | 25.0 | 2 | 108.868408 | 34.201698 |
12 | 12 | 瞪羚路 | 2 | 25.0 | 2 | 108.863556 | 34.201675 |
13 | 13 | 瞪羚路 | 2 | 25.0 | 2 | 108.859413 | 34.201695 |
14 | 14 | 瞪羚路 | 2 | 25.0 | 2 | 108.857033 | 34.201706 |
15 | 15 | 瞪羚路 | 2 | 25.0 | 2 | 108.856926 | 34.201702 |
16 | 16 | 高新六路 | 2 | 25.0 | 3 | 108.877281 | 34.211655 |
17 | 17 | 高新六路 | 2 | 25.0 | 3 | 108.877281 | 34.211735 |
18 | 18 | 高新六路 | 2 | 25.0 | 3 | 108.877266 | 34.212143 |
19 | 19 | 高新六路 | 2 | 25.0 | 3 | 108.877274 | 34.214108 |
20 | 20 | 高新六路 | 2 | 25.0 | 3 | 108.877243 | 34.216526 |
21 | 21 | 高新六路 | 2 | 25.0 | 3 | 108.877243 | 34.220024 |
22 | 22 | 高新六路 | 2 | 25.0 | 3 | 108.877281 | 34.220097 |
23 | 23 | 高新四路 | 2 | 25.0 | 4 | 108.895088 | 34.235291 |
24 | 24 | 高新四路 | 2 | 25.0 | 4 | 108.895073 | 34.235027 |
25 | 25 | 高新四路 | 2 | 25.0 | 4 | 108.895088 | 34.232681 |
26 | 26 | 高新四路 | 2 | 25.0 | 4 | 108.895096 | 34.232456 |
27 | 27 | 高新四路 | 2 | 25.0 | 4 | 108.895058 | 34.231377 |
28 | 28 | 高新四路 | 2 | 25.0 | 4 | 108.895042 | 34.228569 |
29 | 29 | 高新四路 | 2 | 25.0 | 4 | 108.895042 | 34.228458 |
... | ... | ... | ... | ... | ... | ... | ... |
17517 | 17517 | 太華南路 | 0 | NaN | 580 | 108.972366 | 34.278843 |
17518 | 17518 | 太華南路 | 0 | NaN | 580 | 108.972359 | 34.280804 |
17519 | 17519 | 太華南路 | 0 | NaN | 580 | 108.972359 | 34.280850 |
17520 | 17520 | 太華南路 | 0 | NaN | 580 | 108.972336 | 34.280907 |
17521 | 17521 | 太華南路 | 0 | NaN | 580 | 108.972321 | 34.280968 |
17522 | 17522 | 太華南路 | 0 | NaN | 580 | 108.972305 | 34.281017 |
17523 | 17523 | 太華南路 | 0 | NaN | 580 | 108.972267 | 34.281063 |
17524 | 17524 | 太華南路 | 0 | NaN | 580 | 108.972038 | 34.281368 |
17525 | 17525 | 太華南路 | 0 | NaN | 580 | 108.971718 | 34.281731 |
17526 | 17526 | 太華南路 | 0 | NaN | 580 | 108.971619 | 34.281895 |
17527 | 17527 | 太華南路 | 0 | NaN | 580 | 108.971573 | 34.282001 |
17528 | 17528 | 太華南路 | 0 | NaN | 580 | 108.971535 | 34.282070 |
17529 | 17529 | 太華南路 | 0 | NaN | 580 | 108.971535 | 34.282116 |
17530 | 17530 | 太華南路 | 0 | NaN | 580 | 108.971519 | 34.282173 |
17531 | 17531 | 太華南路 | 0 | NaN | 580 | 108.971512 | 34.282421 |
17532 | 17532 | 太華南路 | 0 | NaN | 580 | 108.971558 | 34.285145 |
17533 | 17533 | 太華南路 | 0 | NaN | 580 | 108.971558 | 34.286316 |
17534 | 17534 | 太華南路 | 0 | NaN | 580 | 108.971573 | 34.289368 |
17535 | 17535 | 太華南路 | 0 | NaN | 580 | 108.971573 | 34.292759 |
17536 | 17536 | 太華南路 | 0 | NaN | 580 | 108.971581 | 34.293903 |
17537 | 17537 | 太華南路 | 0 | NaN | 580 | 108.971573 | 34.300178 |
17538 | 17538 | 太華南路 | 0 | NaN | 580 | 108.971581 | 34.301437 |
17539 | 17539 | 太華南路 | 0 | NaN | 580 | 108.971588 | 34.301540 |
17540 | 17540 | 太華南路 | 0 | NaN | 580 | 108.971603 | 34.302830 |
17541 | 17541 | 太華南路 | 0 | NaN | 580 | 108.971603 | 34.303635 |
17542 | 17542 | 太華北路 | 0 | NaN | 581 | 108.971519 | 34.309315 |
17543 | 17543 | 太華北路 | 0 | NaN | 581 | 108.971519 | 34.309181 |
17544 | 17544 | 太華北路 | 0 | NaN | 581 | 108.971512 | 34.307926 |
17545 | 17545 | 太華北路 | 0 | NaN | 581 | 108.971519 | 34.305836 |
17546 | 17546 | 太華北路 | 0 | NaN | 581 | 108.971519 | 34.303631 |
17547 rows × 7 columns
可以看出,每一行代表一個點,每一行的最後兩列爲座標。另外有兩列是我們需要關注的,FID列是數據的自增ID,Num是一個編號。後面的點轉線,將依據這兩列。
用Geopandas將點打印出來,可以看到點的地理分佈情況,如下圖:
xy = [Point(xy) for xy in zip(df.Lng,df.Lat)]
pointDataFrame = gpd.GeoDataFrame(df,geometry=xy)
pointDataFrame.plot()
<matplotlib.axes._subplots.AxesSubplot at 0x276c20cba90>
熟悉GIS矢量數據結構的人都知道,線是由點構成的,其在物理結構上表現的就是一連串有序排列的點。根據這一特徵,我們來進行點轉線操作。
2、點轉線
有規則才成方圓,不,有規則才能連成線,通過查看上面的表,我們按照如下規則,將點轉換爲線:
1、num值相同的點,合併成一根線段;
2、線段上的點的排列順序,按照其在表中的排列順序FID
轉換過程如下:
#分組
dataGroup = df.groupby('Num')
#構造數據
tb = []
geomList = []
for name,group in dataGroup:
# 分離出屬性信息,取每組的第1行前5列作爲數據屬性
tb.append(group.iloc[0,:5])
# 把同一組的點打包到一個list中
xyList = [xy for xy in zip(group.Lng, group.Lat)]
line = LineString(xyList)
geomList.append(line)
# 點轉線
geoDataFrame = gpd.GeoDataFrame(tb, geometry = geomList)
#我們打印下結果看看
geoDataFrame
FID | Name | State | Speed | Num | geometry | |
---|---|---|---|---|---|---|
0 | 0 | 科技六路 | 3 | 10.0 | 0 | LINESTRING (108.888107 34.21166229999999, 108.... |
2 | 2 | 瞪羚路 | 2 | 15.0 | 1 | LINESTRING (108.856926 34.2015953, 108.857033 ... |
9 | 9 | 瞪羚路 | 2 | 25.0 | 2 | LINESTRING (108.869408 34.2017097, 108.869308 ... |
16 | 16 | 高新六路 | 2 | 25.0 | 3 | LINESTRING (108.877281 34.2116547, 108.877281 ... |
23 | 23 | 高新四路 | 2 | 25.0 | 4 | LINESTRING (108.895088 34.2352905, 108.895073 ... |
31 | 31 | 科技一路 | 2 | 20.0 | 5 | LINESTRING (108.900749 34.2257996, 108.900589 ... |
38 | 38 | 210國道 | 1 | 40.0 | 6 | LINESTRING (108.781281 33.8055725, 108.781242 ... |
2914 | 2914 | 210國道 | 1 | 45.0 | 7 | LINESTRING (108.8955 34.19851679999999, 108.89... |
3131 | 3131 | 太白南路 | 1 | 35.0 | 8 | LINESTRING (108.895638 34.1985016, 108.89666 3... |
3174 | 3174 | 丈八三路 | 1 | 30.0 | 9 | LINESTRING (108.875626 34.1899567, 108.87558 3... |
3180 | 3180 | 丈八三路 | 1 | 30.0 | 10 | LINESTRING (108.875481 34.19846339999999, 108.... |
3187 | 3187 | 唐延南路 | 1 | 35.0 | 11 | LINESTRING (108.881477 34.1797485, 108.881508 ... |
3229 | 3229 | 唐延南路 | 1 | 35.0 | 12 | LINESTRING (108.890282 34.19849779999999, 108.... |
3267 | 3267 | 丈八東路 | 1 | 35.0 | 13 | LINESTRING (108.874435 34.2050018, 108.874565 ... |
3339 | 3339 | 丈八東路 | 1 | 35.0 | 14 | LINESTRING (108.945831 34.19813920000001, 108.... |
3408 | 3408 | 丈八六路 | 1 | 35.0 | 15 | LINESTRING (108.855911 34.1825256, 108.855934 ... |
3430 | 3430 | 丈八六路 | 1 | 40.0 | 16 | LINESTRING (108.857033 34.2045937, 108.856934 ... |
3451 | 3451 | 錦業路 | 1 | 35.0 | 17 | LINESTRING (108.841652 34.1938324, 108.841728 ... |
3482 | 3482 | 丈八五路 | 1 | 40.0 | 18 | LINESTRING (108.864204 34.1888275, 108.86409 3... |
3497 | 3497 | 丈八五路 | 1 | 35.0 | 19 | LINESTRING (108.863541 34.20478060000001, 108.... |
3511 | 3511 | 丈八二路 | 1 | 35.0 | 20 | LINESTRING (108.880165 34.1901054, 108.880142 ... |
3518 | 3518 | 丈八二路 | 1 | 35.0 | 21 | LINESTRING (108.884537 34.1985245, 108.884178 ... |
3527 | 3527 | 錦業一路 | 1 | 35.0 | 22 | LINESTRING (108.846642 34.1911011, 108.846901 ... |
3549 | 3549 | 錦業一路 | 1 | 35.0 | 23 | LINESTRING (108.89061 34.1916618, 108.888481 3... |
3572 | 3572 | 丈八四路 | 1 | 35.0 | 24 | LINESTRING (108.869232 34.1797409, 108.869209 ... |
3595 | 3595 | 丈八四路 | 1 | 35.0 | 25 | LINESTRING (108.869316 34.2062225, 108.869308 ... |
3613 | 3613 | 丈八一路 | 1 | 35.0 | 26 | LINESTRING (108.884712 34.1902275, 108.884705 ... |
3624 | 3624 | 科技六路 | 1 | 30.0 | 27 | LINESTRING (108.877266 34.2116547, 108.879601 ... |
3629 | 3629 | 科技六路 | 1 | 30.0 | 28 | LINESTRING (108.889725 34.2116699, 108.892159 ... |
3649 | 3649 | 唐延路 | 1 | 40.0 | 29 | LINESTRING (108.890419 34.19849779999999, 108.... |
... | ... | ... | ... | ... | ... | ... |
16779 | 16779 | 華清西路 | 1 | 40.0 | 552 | LINESTRING (108.995522 34.2850761, 108.995415 ... |
16799 | 16799 | 華清東路 | 1 | 40.0 | 553 | LINESTRING (108.995522 34.2850189, 108.996872 ... |
16818 | 16818 | 華清東路 | 1 | 45.0 | 554 | LINESTRING (109.014343 34.28803629999999, 109.... |
16837 | 16837 | 太華南路 | 1 | 35.0 | 555 | LINESTRING (108.971519 34.30363079999999, 108.... |
16894 | 16894 | 西安高架快速幹道 | 1 | 70.0 | 556 | LINESTRING (108.995911 34.2907372, 108.995949 ... |
16981 | 16981 | 西安高架快速幹道 | 1 | 60.0 | 557 | LINESTRING (109.052925 34.2957687, 109.052406 ... |
17097 | 17097 | 礦山路 | 1 | 30.0 | 558 | LINESTRING (108.995697 34.3014565, 108.996246 ... |
17110 | 17110 | 礦山路 | 1 | 30.0 | 559 | LINESTRING (109.020103 34.3016586, 109.018806 ... |
17130 | 17130 | 玄武路 | 1 | 40.0 | 560 | LINESTRING (108.947319 34.3048973, 108.947769 ... |
17151 | 17151 | 玄武路 | 1 | 30.0 | 561 | LINESTRING (108.971581 34.3058472, 108.971519 ... |
17175 | 17175 | 太元路 | 1 | 35.0 | 562 | LINESTRING (108.971512 34.3014908, 108.971581 ... |
17187 | 17187 | 太元路 | 1 | 30.0 | 563 | LINESTRING (108.995705 34.3015594, 108.995415 ... |
17203 | 17203 | 太和路 | 1 | 30.0 | 564 | LINESTRING (108.984474 34.2986145, 108.984482 ... |
17206 | 17206 | 太和路 | 1 | 30.0 | 565 | LINESTRING (108.98407 34.3100739, 108.98407 34... |
17212 | 17212 | 太華北路 | 1 | 35.0 | 566 | LINESTRING (108.971603 34.3036346, 108.971581 ... |
17240 | 17240 | 太華北路 | 1 | 30.0 | 567 | LINESTRING (108.971588 34.3395691, 108.971588 ... |
17263 | 17263 | 北辰路 | 1 | 40.0 | 568 | LINESTRING (108.995834 34.3084831, 108.995789 ... |
17308 | 17308 | 北辰路 | 1 | 40.0 | 569 | LINESTRING (108.995682 34.3673172, 108.995628 ... |
17341 | 17341 | 含元路 | 1 | 25.0 | 570 | LINESTRING (108.971512 34.2862816, 108.971573 ... |
17365 | 17365 | 含元路 | 1 | 25.0 | 571 | LINESTRING (108.994949 34.29107279999999, 108.... |
17392 | 17392 | 自強東路 | 1 | 25.0 | 572 | LINESTRING (108.947289 34.280201, 108.950539 3... |
17414 | 17414 | 自強東路 | 1 | 25.0 | 573 | LINESTRING (108.950539 34.2802086, 108.947289 ... |
17416 | 17416 | 建強路 | 1 | 30.0 | 574 | LINESTRING (108.955788 34.29272460000001, 108.... |
17427 | 17427 | 建強路 | 1 | 30.0 | 575 | LINESTRING (108.955238 34.3052254, 108.955223 ... |
17439 | 17439 | 龍首北路 | 0 | NaN | 576 | LINESTRING (108.92231 34.2926826, 108.92469 34... |
17465 | 17465 | 龍首北路 | 0 | NaN | 577 | LINESTRING (108.960281 34.29281229999999, 108.... |
17486 | 17486 | 長纓西路 | 0 | NaN | 578 | LINESTRING (108.972626 34.2773285, 108.973923 ... |
17500 | 17500 | 長纓東路 | 0 | NaN | 579 | LINESTRING (108.995468 34.27758789999999, 108.... |
17504 | 17504 | 太華南路 | 0 | NaN | 580 | LINESTRING (108.972733 34.2774429, 108.97271 3... |
17542 | 17542 | 太華北路 | 0 | NaN | 581 | LINESTRING (108.971519 34.30931470000001, 108.... |
582 rows × 6 columns
可以看到,數據已經按Num分組,並合併成了一個LineString對象。
可以通過地圖顯示查看結果。
geoDataFrame.plot()
<matplotlib.axes._subplots.AxesSubplot at 0x276c0abdcc0>