• 125722

    文章

  • 803

    评论

  • 12

    友链

  • 最近新加了换肤功能,大家多来逛逛吧~~~~
  • 喜欢这个网站的朋友可以加一下QQ群,我们一起交流技术。

GeoPandas入门 | 01-地理数据介绍

服了这份高薪指南,涨多少你说了算>>

01-地理数据介绍

1.1 Python地理空间矢量数据简介

%matplotlib inline

import pandas as pd
import geopandas

导入地理数据

地理空间数据通常可以从特定的GIS文件格式或数据存储中获得,如ESRI shapefiles、GeoJSON文件、geopackage文件、PostGIS(PostgreSQL)数据库、...

我们可以使用GeoPandas库中的geopandas.read_file函数,来读取其中的很多GIS文件格式(依靠的是fiona库,它是GDAL/OGR的python接口)。

例如,我们先读取一个包含世界所有国家边界的shapefile文件,zip文件放到在/data目录下)。

countries=geopandas.read_file("zip://data/ne_110m_admin_0_countries.zip")
countries.head()

<div> <style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style> <table border="1" class="dataframe"> <thead> <tr style="text-align: right;"> <th></th> <th>featurecla</th> <th>scalerank</th> <th>LABELRANK</th> <th>SOVEREIGNT</th> <th>SOV_A3</th> <th>ADM0_DIF</th> <th>LEVEL</th> <th>TYPE</th> <th>ADMIN</th> <th>ADM0_A3</th> <th>...</th> <th>NAME_KO</th> <th>NAME_NL</th> <th>NAME_PL</th> <th>NAME_PT</th> <th>NAME_RU</th> <th>NAME_SV</th> <th>NAME_TR</th> <th>NAME_VI</th> <th>NAME_ZH</th> <th>geometry</th> </tr> </thead> <tbody> <tr> <th>0</th> <td>Admin-0 country</td> <td>1</td> <td>6</td> <td>Fiji</td> <td>FJI</td> <td>0</td> <td>2</td> <td>Sovereign country</td> <td>Fiji</td> <td>FJI</td> <td>...</td> <td>피지</td> <td>Fiji</td> <td>Fidżi</td> <td>Fiji</td> <td>Фиджи</td> <td>Fiji</td> <td>Fiji</td> <td>Fiji</td> <td>斐濟</td> <td>MULTIPOLYGON (((180.00000 -16.06713, 180.00000...</td> </tr> <tr> <th>1</th> <td>Admin-0 country</td> <td>1</td> <td>3</td> <td>United Republic of Tanzania</td> <td>TZA</td> <td>0</td> <td>2</td> <td>Sovereign country</td> <td>United Republic of Tanzania</td> <td>TZA</td> <td>...</td> <td>탄자니아</td> <td>Tanzania</td> <td>Tanzania</td> <td>Tanzânia</td> <td>Танзания</td> <td>Tanzania</td> <td>Tanzanya</td> <td>Tanzania</td> <td>坦桑尼亚</td> <td>POLYGON ((33.90371 -0.95000, 34.07262 -1.05982...</td> </tr> <tr> <th>2</th> <td>Admin-0 country</td> <td>1</td> <td>7</td> <td>Western Sahara</td> <td>SAH</td> <td>0</td> <td>2</td> <td>Indeterminate</td> <td>Western Sahara</td> <td>SAH</td> <td>...</td> <td>서사하라</td> <td>Westelijke Sahara</td> <td>Sahara Zachodnia</td> <td>Saara Ocidental</td> <td>Западная Сахара</td> <td>Västsahara</td> <td>Batı Sahra</td> <td>Tây Sahara</td> <td>西撒哈拉</td> <td>POLYGON ((-8.66559 27.65643, -8.66512 27.58948...</td> </tr> <tr> <th>3</th> <td>Admin-0 country</td> <td>1</td> <td>2</td> <td>Canada</td> <td>CAN</td> <td>0</td> <td>2</td> <td>Sovereign country</td> <td>Canada</td> <td>CAN</td> <td>...</td> <td>캐나다</td> <td>Canada</td> <td>Kanada</td> <td>Canadá</td> <td>Канада</td> <td>Kanada</td> <td>Kanada</td> <td>Canada</td> <td>加拿大</td> <td>MULTIPOLYGON (((-122.84000 49.00000, -122.9742...</td> </tr> <tr> <th>4</th> <td>Admin-0 country</td> <td>1</td> <td>2</td> <td>United States of America</td> <td>US1</td> <td>1</td> <td>2</td> <td>Country</td> <td>United States of America</td> <td>USA</td> <td>...</td> <td>미국</td> <td>Verenigde Staten van Amerika</td> <td>Stany Zjednoczone</td> <td>Estados Unidos</td> <td>Соединённые Штаты Америки</td> <td>USA</td> <td>Amerika Birleşik Devletleri</td> <td>Hoa Kỳ</td> <td>美国</td> <td>MULTIPOLYGON (((-122.84000 49.00000, -120.0000...</td> </tr> </tbody> </table> <p>5 rows × 95 columns</p> </div>

countries.plot()
<matplotlib.axes._subplots.AxesSubplot at 0x7f687bb78a58>

png

我们可以观察到:

  • 使用 .head()可以得到数据集的前五列,就像使用Pandas一样
  • 有一个 geometry列,用于存储不同的国家的边界多边形
  • 我们可以使用 .plot()方法来快速得到数据的基本可视化效果

1.2 GeoDataFrame 介绍

我们使用GeoPandas库来读取地理空间数据,然后返回一个GeoDataFrame对象。

type(countries)
geopandas.geodataframe.GeoDataFrame
  • 一个GeoDataFrame包含一个表格式的地理空间数据集

  • 它有一个geometry列,用来保存几何信息(或GeoJSON要素)

  • 其他列是描述每个几何体的属性(或GeoJSON属性)

  • 这样的GeoDataFrame就像pandas.DataFrame一样,但它具有一些额外的功能,用于处理地理空间数据

  • 一个.geometry属性,总是返回带有几何信息的列(返回一个GeoSeries)。列名本身不一定是 geometry,但它总是作为.geometry属性被访问。

  • 它有一些额外的方法来处理空间数据(面积、距离、缓冲区、交叉点......),我们将在后面的教程中看到

countries.geometry
0      MULTIPOLYGON (((180.00000 -16.06713, 180.00000...
1      POLYGON ((33.90371 -0.95000, 34.07262 -1.05982...
2      POLYGON ((-8.66559 27.65643, -8.66512 27.58948...
3      MULTIPOLYGON (((-122.84000 49.00000, -122.9742...
4      MULTIPOLYGON (((-122.84000 49.00000, -120.0000...
                             ...                        
172    POLYGON ((18.82982 45.90887, 18.82984 45.90888...
173    POLYGON ((20.07070 42.58863, 19.80161 42.50009...
174    POLYGON ((20.59025 41.85541, 20.52295 42.21787...
175    POLYGON ((-61.68000 10.76000, -61.10500 10.890...
176    POLYGON ((30.83385 3.50917, 29.95350 4.17370, ...
Name: geometry, Length: 177, dtype: geometry
type(countries.geometry)
geopandas.geoseries.GeoSeries
countries.geometry.area
0         1.639511
1        76.301964
2         8.603984
3      1712.995228
4      1122.281921
          ...     
172       8.604719
173       1.479321
174       1.231641
175       0.639000
176      51.196106
Length: 177, dtype: float64

它仍然是一个DataFrame,所以我们可以在地理空间数据集上使用所有的pandas功能,并对属性和几何信息一起进行数据操作

例如,我们可以计算所有国家的平均人口数量(通过访问'POP_EST'列,并调用平均值方法)。

countries['POP_EST'].mean() # 计算所有国家的平均人口数量
41712369.84180791

或者,我们可以使用布尔筛选器,根据条件选择数据框的一个子集

africa=countries[countries['CONTINENT']=='Africa']
africa.plot()
<matplotlib.axes._subplots.AxesSubplot at 0x7f6877ec5940>

png

本教程的其余部分将假设你已经知道一些Pandas的基础知识,但我们会尽量为那些不熟悉的人提供这部分的提示

如果你想了解更多关于pandas的知识,可以参考一些资源

知识点:

  • GeoDataFrame 可以将典型的表格数据分析与空间操作结合起来进行
  • GeoDataFrame(或要素集,Feature Collection)由以下部分组成:
    • Geometriesfeatures:空间对象
    • Attributesproperties:包含每个空间对象的非空间信息的列

1.3 矢量要素:点、线、面

空间矢量数据可以包括不同的类型,3种基本类型是:

矢量数据类型

  • 点数据:表示空间中的一个点
  • 线条数据(LineString):表示构成一条线的点的序列
  • 多边形数据:表示一个填充区域

它们中的每一个都可以组合成多部分的矢量数据(参见https://shapely.readthedocs.io/en/stable/manual.html#geometric-objects 查看详细的概述)。在我们目前看到的例子中,各个矢量对象都是多边形

print(countries.geometry[2])
POLYGON ((-8.665589565454809 27.65642588959236, -8.665124477564191 27.58947907155823, -8.684399786809053 27.39574412689601, -8.6872936670174 25.88105621998891, -11.96941891117116 25.93335276946827, -11.93722449385332 23.37459422453617, -12.87422156416958 23.28483226164518, -13.11875444177471 22.77122020109626, -12.92910193526353 21.32707062426756, -16.84519365077399 21.33332347257488, -17.06342322434257 20.99975210213083, -17.02042843267577 21.42231028898158, -17.00296179856109 21.42073415779658, -14.75095455571353 21.50060008390366, -14.63083268885107 21.8609398462749, -14.22116777185725 22.31016307218816, -13.89111039880905 23.6910090194593, -12.50096269372537 24.7701162785782, -12.03075883630163 26.03086619720307, -11.71821977380036 26.10409170176062, -11.39255489749701 26.88342397715439, -10.55126257978527 26.99080760345689, -10.18942420087758 26.86094472910741, -9.735343390328879 26.86094472910741, -9.41303748212448 27.08847606048857, -8.794883999049077 27.12069631602251, -8.817828334986672 27.65642588959236, -8.665589565454809 27.65642588959236))

让我们导入一些其他具有不同类型几何对象的数据集:

一个世界各城市数据集,由Point数据组成

cities = geopandas.read_file("zip://data/ne_110m_populated_places.zip")
print(cities.geometry[0])
POINT (12.45338654497177 41.90328217996012)

还有一个世界河流的数据集,zip文件在/data目录下,每条河流都是一条LineString

# ! wget https://naciscdn.org/naturalearth/50m/physical/ne_50m_rivers_lake_centerlines.zip
--2020-08-12 00:23:33--  https://naciscdn.org/naturalearth/50m/physical/ne_50m_rivers_lake_centerlines.zip
Resolving naciscdn.org (naciscdn.org)... 146.201.97.163
Connecting to naciscdn.org (naciscdn.org)|146.201.97.163|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 457951 (447K) [application/zip]
Saving to: ‘ne_50m_rivers_lake_centerlines.zip’

ne_50m_rivers_lake_ 100%[===================>] 447.22K  8.16KB/s    in 53s     

2020-08-12 00:24:31 (8.43 KB/s) - ‘ne_50m_rivers_lake_centerlines.zip’ saved [457951/457951]
rivers = geopandas.read_file("zip://data/ne_50m_rivers_lake_centerlines.zip")
print(rivers.geometry[0])
LINESTRING (51.9371337598152 55.70106609892139, 51.88086646731369 55.68625891701544, 51.82031249962222 55.69745514553858, 51.7476018274624 55.69366250841807, 51.6628417966117 55.60817291874525, 51.57871093775964 55.59943268477065, 51.51342773400279 55.58312409100404, 51.50854492161091 55.52948639548083, 51.48583984403365 55.49640534033426, 51.36914062543957 55.46796295772435, 51.21306254869774 55.50264985760492, 51.13452148447897 55.48273346527725, 51.07934570274205 55.46759674659262, 50.98022460947817 55.46637604371949, 50.83445217522774 55.45630956063775, 50.6883789060617 55.42011139502489, 50.4118652342932 55.40119049644431, 50.07802734358711 55.38112213757665, 49.82216796867687 55.33466217681809, 49.53222656260584 55.260614325191, 49.38232421848795 55.17182037990665, 49.24808475131027 55.11301870345045)

1.4 shapely库简介

各个Geometry对象由shapely库提供支持

type(countries.geometry[0])
shapely.geometry.multipolygon.MultiPolygon

下面是使用shapely构建矢量要素的方法

from shapely.geometry import Point, Polygon, LineString
p=Point(0,0)
print(p)
POINT (0 0)
polygon=Polygon([(1,1),(2,2),(2,1)])
polygon.area
0.5
polygon.distance(p) # 多边形到点的最近距离
1.4142135623730951

知识点:

  • GeoPandas中的矢量对象是由shapely库继承得到的
  • 如果访问一个GeoDataFrame的geometry对象,则得到一个shapely几何体对象
  • 这些对象具有类似于geopandas对象(GeoDataFrame/GeoSeries)的功能

1.5 图层叠加显示

ax=countries.plot(edgecolor='k',facecolor='none',figsize=(15,10))
rivers.plot(ax=ax)
cities.plot(ax=ax,color='red')
ax.set(xlim=(73,135),ylim=(0,55))
[(0.0, 55.0), (73.0, 135.0)]

png

参见04-更多关于可视化,了解更多关于地理空间数据集可视化的细节

1.6 本章练习

在本课程的练习中,我们将使用几个关于巴黎市的数据集:

1.6.1 练习一

  • 探索自行车站点数据data/paris_bike_stations_mercator.gpkg
    • 读取stations数据集
    • 检查读取返回对象的类型type()
    • 检查数据框的第一行,探索这个数据集包含什么样的矢量要素及其字段
    • 检查数据集中的要素的数量
stations=geopandas.read_file('data/paris_bike_stations_mercator.gpkg')
type(stations)
geopandas.geodataframe.GeoDataFrame
stations.head()

<div> <style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style> <table border="1" class="dataframe"> <thead> <tr style="text-align: right;"> <th></th> <th>name</th> <th>bike_stands</th> <th>available_bikes</th> <th>geometry</th> </tr> </thead> <tbody> <tr> <th>0</th> <td>14002 - RASPAIL QUINET</td> <td>44</td> <td>4</td> <td>POINT (259324.887 6247620.771)</td> </tr> <tr> <th>1</th> <td>20503 - COURS DE VINCENNES PYRÉNÉES</td> <td>21</td> <td>3</td> <td>POINT (267824.377 6249062.894)</td> </tr> <tr> <th>2</th> <td>20011 - PYRÉNÉES-DAGORNO</td> <td>21</td> <td>0</td> <td>POINT (267742.135 6250378.469)</td> </tr> <tr> <th>3</th> <td>31008 - VINCENNES (MONTREUIL)</td> <td>56</td> <td>0</td> <td>POINT (271326.638 6250750.824)</td> </tr> <tr> <th>4</th> <td>43006 - MINIMES (VINCENNES)</td> <td>28</td> <td>27</td> <td>POINT (270594.689 6248007.705)</td> </tr> </tbody> </table> </div>

stations.shape
(1226, 4)

1.6.2 练习二

  • station的快速可视化实现
  • 使用figsize参数调整可视化图片大小
stations.plot()
<matplotlib.axes._subplots.AxesSubplot at 0x7f68747183c8>

png

stations.plot(figsize=(12,6))
<matplotlib.axes._subplots.AxesSubplot at 0x7f6874fd1fd0>

png

一个只显示点的图,如果没有任何空间背景,是很难解释的。因此,在接下来的练习中,我们将学习如何添加背景图。

我们要利用contextily包,这个包的add_basemap()函数可以很容易地给我们的绘图添加一个网络地图背景。我们首先绘制数据,然后将matplotlib axes对象(由dataframeplot()方法返回)传递给add_basemap()函数,然后contextily将下载你的绘图地理范围所需的地图瓦片

# ! pip3 install contextily
import contextily
axes=stations.plot(figsize=(12,6), markersize=5)
contextily.add_basemap(axes)

png

1.6.3 练习三

  • 做一个统计直方图,显示的自行车站数量分布情况
stations['bike_stands'].hist()
<matplotlib.axes._subplots.AxesSubplot at 0x7f687abd5c50>

png




695856371Web网页设计师②群 | 喜欢本站的朋友可以收藏本站,或者加入我们大家一起来交流技术!

0条评论

Loading...


自定义皮肤 主体内容背景
打开支付宝扫码付款购买视频教程
遇到问题联系客服QQ:419400980
注册梁钟霖个人博客