Python GeoPandas Tutorial

Python GeoPandas Tutorial

1. 读写数据

A. 查看支持的文件类型

import pandas as gpd
# Check supported format drivers
gpd.io.file.fiona.drvsupport.supported_drivers

# 等价于
import fiona
fiona.supported_drivers

B. 读取文件

gpd.read_file()
# 读取 url,geojson 文件
gpd.read_file("http://*/data.geojson", river="GeoJSON")
# 读取 zip 文件中的 shp 文件
gpd.read_file("zip:///data_shp.zip!data/location.shp")

主要参数:

  • driver:指定文件格式,默认为 .shp 文件
  • crs:设置坐标系

C. 写入文件

GeoDataFrame.to_file()  # driver 参数 指定文件格式
GeoDataFrame.to_wkb()
GeoDataFrame.to_wkt()

D. GeoDataFrame 初始化

主要参数

  • geometry:应当为 geopandas.GeoSeries;或者 list 类型,元素为 shapely.geometry 下类型

  • crs:地理坐标系

实例

from shapely.geometry import Point
# 'geometry' 列指明 geometry 参数
data = {'col1': ['name1', 'name2'], 'geometry': [Point(1, 2), Point(2, 1)]}
gdf = geopandas.GeoDataFrame(data, crs="EPSG:4326")

2. 主要方法

geopandas.GeoSeries 主要方法:site

geopandas.GeoDataFrame 主要方法:site

2.1 空间分析方法

2.1.1 空间连接 Spatial join

属性连接(Attribute Joins):Pandas 库中 pandas.join() 方法

空间连接(Spatial join):GeoPandas 库中 geopandas.sjoin() 方法

  • 通过参数 predicate 指定几何关系,实现连接

如:left_df=cities 为城市,geomtery 属性为 Point 类型,right_df=countries 为国家,geomtery 属性为 Polygon 类型。通过下述函数,可以实现城市和国家的匹配

geopandas.sjoin(left_df=cities, right_df=countries, how="left", predicate='within')

最邻近空间连接:geopandas.sjoin_nearest()

主要参数:

  • left_df, right_df (geopandas.geodataframe.GeoDataFrame)

  • how (str)'left', 'right', 'inner'

  • max_distance (float)

  • lsuffix, rsuffix (str)

  • distance_col (str):保存连接的几何对象的距离

2.1.2 Overlay

element-wise 操作,参考:

3. Geocoding in Geopandas

3.1 地理编码工具

3.2 GeoPy

A. Nominatim

Nominatim: 基于 OSM 的地理编码:官网在线查询

初始化:

geolocator = Nominatim(user_agent="my_application")
# 建议定义 user_agent 名称

地理编码.geocode() 方法

loc = geolocator.geocode(query, *)

主要参数

  • query (str or dict)

    • 对于 dict 类型:其 key 为 street, city, county, state, country, postalcode
  • exactly_one (bool)

    • True 表示只返回一个最接近的结果

    • False,返回 list 类型,返回所有查询结果

  • addressdetails (bool):是否返回地址的详细结果

  • country_codes (str or list):通过 country code(s) 将查询范围现在指定的国家内

    • ISO 3166-1alpha2 code:site
  • viewbox (list or tuple):包含两个元素的 list 或 tuple,每个元素为 geopy.point.Point(latitude, longitude)"%(latitude)s, %(longitude)s"

    • 将查询范围限制在指定的 box 内,只有设置参数 bounded=True 才会生效
  • bounded (bool):是否将查询范围限制在 viewbox 参数指定的 box 内

返回结果None, 或 geopy.location.Location,或 list(当设置 exactly_one = False)。geopy.location.Location 类主要属性有:

  • .address

  • .latitude, .longitude, .altitude

  • .point:返回 geopy.point.Point 类型

  • .raw

逆地理编码.inverse() 方法

loc = geolocator.geocode(query, *)

主要参数

  • query:包含两个元素的 list 或 tuple,每个元素为 geopy.point.Point(latitude, longitude)"%(latitude)s, %(longitude)s"

实例: 地理编码 .geocode() 方法

from geopy.geocoders import Nominatim
# 初始化一个 Nominatim 实例
geolocator = Nominatim(user_agent="my_application")

query = "National University of Singapore"
res = geolocator.geocode(query, exactly_one=True, country_codes="sg")

print(res.point)
print(res.address)
print(res.raw)

3.2.2 RateLimiter

OSM 的 Nominatim 限制 API 请求频率在 1 秒以上,参见 site

GeoPy 库中 geopy.extra.rate_limiter.RateLimiter() 用于控制 API 请求频率。

实例:

from geopy.geocoders import Nominatim
from geopy.extra.rate_limiter import RateLimiter
geolocator = Nominatim(user_agent="my_app")

# 使用 RateLimiter 类 wrap geolocator.geocode() 方法
geocode = RateLimiter(geolocator.geocode, min_delay_seconds=1.)
# 传入 geolocator.geocode() 方法的参数
res = geocode(query='nus', country_codes="sg", exactly_one=True) 
# 输出
print(res.address)
print(res.location)

实例:pandas.DataFrame 中的地址信息实现地理编码

import pandas as pd
from geopy.geocoders import Nominatim
from geopy.extra.rate_limiter import RateLimiter
# 待解析地址
df = pd.DataFrame({'name': ['nus', 'ntu', 'smu']})

geolocator = Nominatim(user_agent="my_app")
geocode = RateLimiter(geolocator.geocode, min_delay_seconds=1.)  # 请求间隔为 1 s

df['location'] = df['name'].apply(geocode, 
                                  country_codes='sg', exactly_one=True)  # 传入到 geocode 中的参数
df['point'] = df['location'].apply(lambda loc: tuple(loc.point) if loc else None)  # 从请求结果中提取 经纬度坐标
df['address'] = df['location'].apply(lambda loc: loc.address if loc else None)     # 从请求结果中提取 地址

3.3 geopandas.tools.geocode() 方法

实际上,该方法通过 geopy 库实现

Geocoding in Geopandas:site

geopandas.tools.geocodesite

实例: 使用 geopandas.tools.geocode() 方法

import pandas as pd
import geopandas as gpd

df = pd.Series(['nus', 'ntu', 'smu'])
df = gpd.tools.geocode(df, provider='nominatim', user_agent='my_app')

该方法存在的缺点:无法设置 geopy 库中 .geocode() 方法的参数。因此,推荐使用 3.2 节中的实例方法。

posted @ 2022-06-03 09:57  veager  阅读(235)  评论(0)    收藏  举报