使用 GeoPandas 读取 Python 中的 GRASS 矢量数据源
Read GRASS vector datasources in Python using GeoPandas
我正在尝试将 GRASS GIS
矢量图层读入 GeoPandas Dataframe
。
因为我无法在 Fiona
see related issue
中启用 GRASS GIS
(只读)驱动程序
我做了一个 "hackish" 方法(有效)将 GRASS GIS
向量层读入 GeoPandas Dataframe
:
import os
from osgeo import ogr
import pandas as pd
from shapely import wkt
import geopandas as gpd
def grass2gpd(layername, grassdb, location_name, mapset):
datafile = os.path.join(GRASSDB, LOCATION_NAME, MAPSET, 'vector', layername, 'head')
driver = ogr.GetDriverByName('GRASS')
# here the data is read in readonly mode, but also the GDAL GRASS driver has no write capabilities
# I am not sure at the end of the method on how to properly close the datasource (and, actually, if I have to ... )
dataSource = driver.Open(datafile, 0)
layer = dataSource.GetLayer()
srs = layer.GetSpatialRef().ExportToWkt()
lyrDefn = layer.GetLayerDefn()
fieldnames = []
for i in range( lyrDefn.GetFieldCount() ):
fieldnames.append(lyrDefn.GetFieldDefn(i).GetName() )
# hack to avoid to call `layer.ResetReading()` and iterate again over the features
#
# I first build a list of dictionaries
# each element of the list is of the form:
# {geom: WKT_Geometry
# attr: {field_1: val, field_2: val, ..., field_N: val}}
# So the attr key is a dictionary itself
# the nested loop first get the feature then create a dictionary of attributes looping over the list of fields
#
wktgeom = [{'geom':feature.GetGeometryRef().ExportToWkt(),
'attr':{i:feature.GetField(i) for i in fieldnames}} for feature in layer]
# At this point I should close or unlink the datasource, but I can't find the right method to do it
#
# Create a dataframe from the list of dictionaries
#
df = pd.DataFrame(wktgeom)
# convert the WKT string to a shapely WKT object
# concatenate a Geometry dataframe with an attribute dataframe
df_geom = pd.concat([df['geom'].apply(wkt.loads),
pd.DataFrame(list(df['attr'].values))],
axis=1, sort=False)
# transform the pandas dataframe into a geopandas dataframe
gdf = gpd.GeoDataFrame(df_geom, geometry='geom', crs=srs)
return gdf
运行 例如:
GRASSDB="/home/epinux/Data/grassdata"
LOCATION_NAME="lonlat"
MAPSET="PERMANENT"
layername="img_left_filteredBS"
gdf = grass2gpd(layername=layername,
grassdb=GRASSDB,
location_name=LOCATION_NAME,
mapset=MAPSET)
type(gdf)
# returns
# geopandas.geodataframe.GeoDataFrame
该方法将 return 一个 geopandas.geodataframe.GeoDataFrame
,如我所愿,但是...
我想知道是否存在直接传递到 GeoPandas
由 GDAL-OGR Python
接口读取的 OGR 数据源的方法。如果没有,你有什么建议可以改进我做的 "hackish method" 吗?我在代码中添加了一些内联注释,试图解释我的顾虑。
我刚刚收到 Issue I opened on GitHub 的回复,通过在 Fiona
中启用 OGR_GRASS
驱动程序解决了问题,下面的代码工作正常:
import fiona
import geopandas as gpd
fiona.supported_drivers["OGR_GRASS"] = "r"
gdf = gpd.read_file('/GRASSDB/LOCATION_NAME/MAPSET/vector/layername/head')
我正在尝试将 GRASS GIS
矢量图层读入 GeoPandas Dataframe
。
因为我无法在 Fiona
see related issue
GRASS GIS
(只读)驱动程序
我做了一个 "hackish" 方法(有效)将 GRASS GIS
向量层读入 GeoPandas Dataframe
:
import os
from osgeo import ogr
import pandas as pd
from shapely import wkt
import geopandas as gpd
def grass2gpd(layername, grassdb, location_name, mapset):
datafile = os.path.join(GRASSDB, LOCATION_NAME, MAPSET, 'vector', layername, 'head')
driver = ogr.GetDriverByName('GRASS')
# here the data is read in readonly mode, but also the GDAL GRASS driver has no write capabilities
# I am not sure at the end of the method on how to properly close the datasource (and, actually, if I have to ... )
dataSource = driver.Open(datafile, 0)
layer = dataSource.GetLayer()
srs = layer.GetSpatialRef().ExportToWkt()
lyrDefn = layer.GetLayerDefn()
fieldnames = []
for i in range( lyrDefn.GetFieldCount() ):
fieldnames.append(lyrDefn.GetFieldDefn(i).GetName() )
# hack to avoid to call `layer.ResetReading()` and iterate again over the features
#
# I first build a list of dictionaries
# each element of the list is of the form:
# {geom: WKT_Geometry
# attr: {field_1: val, field_2: val, ..., field_N: val}}
# So the attr key is a dictionary itself
# the nested loop first get the feature then create a dictionary of attributes looping over the list of fields
#
wktgeom = [{'geom':feature.GetGeometryRef().ExportToWkt(),
'attr':{i:feature.GetField(i) for i in fieldnames}} for feature in layer]
# At this point I should close or unlink the datasource, but I can't find the right method to do it
#
# Create a dataframe from the list of dictionaries
#
df = pd.DataFrame(wktgeom)
# convert the WKT string to a shapely WKT object
# concatenate a Geometry dataframe with an attribute dataframe
df_geom = pd.concat([df['geom'].apply(wkt.loads),
pd.DataFrame(list(df['attr'].values))],
axis=1, sort=False)
# transform the pandas dataframe into a geopandas dataframe
gdf = gpd.GeoDataFrame(df_geom, geometry='geom', crs=srs)
return gdf
运行 例如:
GRASSDB="/home/epinux/Data/grassdata"
LOCATION_NAME="lonlat"
MAPSET="PERMANENT"
layername="img_left_filteredBS"
gdf = grass2gpd(layername=layername,
grassdb=GRASSDB,
location_name=LOCATION_NAME,
mapset=MAPSET)
type(gdf)
# returns
# geopandas.geodataframe.GeoDataFrame
该方法将 return 一个 geopandas.geodataframe.GeoDataFrame
,如我所愿,但是...
我想知道是否存在直接传递到 GeoPandas
由 GDAL-OGR Python
接口读取的 OGR 数据源的方法。如果没有,你有什么建议可以改进我做的 "hackish method" 吗?我在代码中添加了一些内联注释,试图解释我的顾虑。
我刚刚收到 Issue I opened on GitHub 的回复,通过在 Fiona
中启用 OGR_GRASS
驱动程序解决了问题,下面的代码工作正常:
import fiona
import geopandas as gpd
fiona.supported_drivers["OGR_GRASS"] = "r"
gdf = gpd.read_file('/GRASSDB/LOCATION_NAME/MAPSET/vector/layername/head')