将 mssql 空间字段导入 geopandas/shapely 几何
Import mssql spatial fields into geopandas/shapely geometry
我似乎无法直接将 mssql 空间字段导入 geopandas。我可以使用 Pymssql 将普通的 mssql 表导入到 pandas 中而不会出现问题,但我无法找到将空间场导入到匀称几何体中的方法。我知道 mssql 的 OGR 驱动程序应该能够处理它,但我在 sql 方面不够熟练,无法解决这个问题。
这对于线和多边形来说是一个更大的问题,因为点可以从 mssql 字段转换为 x 和 y 坐标。
谢谢!
我通过正确查询 sql 数据库 table 并通过 shapely.wkt.
中的加载函数将 wkt 字符串转换为匀称的几何图形来解决这个问题
我不是程序员,所以在组织函数时请记住这一点。该函数可以导入 mssql tables 有或没有 GIS 几何。
from pymssql import connect
from pandas import read_sql
from shapely.wkt import loads
from geopandas import GeoDataFrame
def rd_sql(server, database, table, col_names=None, where_col=None, where_val=None, geo_col=False, epsg=2193, export=False, path='save.csv'):
"""
Imports data from MSSQL database, returns GeoDataFrame. Specific columns can be selected and specific queries within columns can be selected. Requires the pymssql package, which must be separately installed.
Arguments:
server -- The server name (str). e.g.: 'SQL2012PROD03'
database -- The specific database within the server (str). e.g.: 'LowFlows'
table -- The specific table within the database (str). e.g.: 'LowFlowSiteRestrictionDaily'
col_names -- The column names that should be retrieved (list). e.g.: ['SiteID', 'BandNo', 'RecordNo']
where_col -- The sql statement related to a specific column for selection (must be formated according to the example). e.g.: 'SnapshotType'
where_val -- The WHERE query values for the where_col (list). e.g. ['value1', 'value2']
geo_col -- Is there a geometry column in the table?
epsg -- The coordinate system (int)
export -- Should the data be exported
path -- The path and csv name for the export if 'export' is True (str)
"""
if col_names is None and where_col is None:
stmt1 = 'SELECT * FROM ' + table
elif where_col is None:
stmt1 = 'SELECT ' + str(col_names).replace('\'', '"')[1:-1] + ' FROM ' + table
else:
stmt1 = 'SELECT ' + str(col_names).replace('\'', '"')[1:-1] + ' FROM ' + table + ' WHERE ' + str([where_col]).replace('\'', '"')[1:-1] + ' IN (' + str(where_val)[1:-1] + ')'
conn = connect(server, database=database)
df = read_sql(stmt1, conn)
## Read in geometry if required
if geo_col:
geo_col_stmt = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=" + "\'" + table + "\'" + " AND DATA_TYPE='geometry'"
geo_col = str(read_sql(geo_col_stmt, conn).iloc[0,0])
if where_col is None:
stmt2 = 'SELECT ' + geo_col + '.STGeometryN(1).ToString()' + ' FROM ' + table
else:
stmt2 = 'SELECT ' + geo_col + '.STGeometryN(1).ToString()' + ' FROM ' + table + ' WHERE ' + str([where_col]).replace('\'', '"')[1:-1] + ' IN (' + str(where_val)[1:-1] + ')'
df2 = read_sql(stmt2, conn)
df2.columns = ['geometry']
geometry = [loads(x) for x in df2.geometry]
df = GeoDataFrame(df, geometry=geometry, crs={'init' :'epsg:' + str(epsg)})
if export:
df.to_csv(path, index=False)
conn.close()
return(df)
编辑:使函数自动查找存在的几何字段。
喜欢这个功能,感谢 Dryden 提供的功能,但是提取几何体的代码在多多边形字段方面存在问题。如果其中一条记录的几何形状是多面体,并且您使用 .STGeometryN(1) 代码,那么您只会获得记录中可能存在的多个多边形中的第一个。地理数据框不会以 record.ID 的总几何结束,您调整代码并删除它应该处理多边形的 .STGeometryN(1)。
我用它来提取我存储在 SQL 服务器中的人口普查块组,并进行了一些调整(应该包括数据库模式参数)我让它工作但我会警告其他人使用它作为是确保您首先在 SQL 中使用此查询知道您的数据中是否有多面体。
select geometrycolumn.STGeometryType(),
,geometrycolumn.STNumGeometries()
from yourtable
order by 1
这会告诉您是否有多个多边形以及每条记录有多少个。
老问题,但如果有人登陆这里,这是另一个解决方案。
如果您确保 return 几何图形作为 WKB(即 [geoField].STAsBinary() AS geometry
),您可以使用 shapely.wkb.loads
函数
加载它们
import pandas as pd
import geopandas as gpd
from shapely.wkb import loads
# define your connection, pymmssql, sqlAlchemy, pyodbc whatever
cnxn = DEFINE_CONNECTION
query = """SELECT [field1]
,[geoField].STAsBinary() AS geometry
,[someOtherFieldYouWant]
FROM [database].[dbo].[table]
"""
df = pd.read_sql(query, cnxn)
gdf = gpd.GeoDataFrame(df)
gdf.loc[:,'geometry'] = gdf.loc[:,'geometry'].apply(loads)
gdf = gdf.set_crs(4326) # OR whatever your CRS is
您可以从 table 中的几何图形的 SRID 中获取 CRS(这假设它们都是相同的,不知道它们是否必须如此)。
query = """SELECT TOP 1 [geoField].STSrid
FROM [database].[dbo].[table]"""
EPSG_AS_INT = pd.read_sql(query, cnxn).squeeze()
然后 gdf = gdf.set_crs(EPSG_AS_INT)
我似乎无法直接将 mssql 空间字段导入 geopandas。我可以使用 Pymssql 将普通的 mssql 表导入到 pandas 中而不会出现问题,但我无法找到将空间场导入到匀称几何体中的方法。我知道 mssql 的 OGR 驱动程序应该能够处理它,但我在 sql 方面不够熟练,无法解决这个问题。 这对于线和多边形来说是一个更大的问题,因为点可以从 mssql 字段转换为 x 和 y 坐标。 谢谢!
我通过正确查询 sql 数据库 table 并通过 shapely.wkt.
中的加载函数将 wkt 字符串转换为匀称的几何图形来解决这个问题我不是程序员,所以在组织函数时请记住这一点。该函数可以导入 mssql tables 有或没有 GIS 几何。
from pymssql import connect
from pandas import read_sql
from shapely.wkt import loads
from geopandas import GeoDataFrame
def rd_sql(server, database, table, col_names=None, where_col=None, where_val=None, geo_col=False, epsg=2193, export=False, path='save.csv'):
"""
Imports data from MSSQL database, returns GeoDataFrame. Specific columns can be selected and specific queries within columns can be selected. Requires the pymssql package, which must be separately installed.
Arguments:
server -- The server name (str). e.g.: 'SQL2012PROD03'
database -- The specific database within the server (str). e.g.: 'LowFlows'
table -- The specific table within the database (str). e.g.: 'LowFlowSiteRestrictionDaily'
col_names -- The column names that should be retrieved (list). e.g.: ['SiteID', 'BandNo', 'RecordNo']
where_col -- The sql statement related to a specific column for selection (must be formated according to the example). e.g.: 'SnapshotType'
where_val -- The WHERE query values for the where_col (list). e.g. ['value1', 'value2']
geo_col -- Is there a geometry column in the table?
epsg -- The coordinate system (int)
export -- Should the data be exported
path -- The path and csv name for the export if 'export' is True (str)
"""
if col_names is None and where_col is None:
stmt1 = 'SELECT * FROM ' + table
elif where_col is None:
stmt1 = 'SELECT ' + str(col_names).replace('\'', '"')[1:-1] + ' FROM ' + table
else:
stmt1 = 'SELECT ' + str(col_names).replace('\'', '"')[1:-1] + ' FROM ' + table + ' WHERE ' + str([where_col]).replace('\'', '"')[1:-1] + ' IN (' + str(where_val)[1:-1] + ')'
conn = connect(server, database=database)
df = read_sql(stmt1, conn)
## Read in geometry if required
if geo_col:
geo_col_stmt = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=" + "\'" + table + "\'" + " AND DATA_TYPE='geometry'"
geo_col = str(read_sql(geo_col_stmt, conn).iloc[0,0])
if where_col is None:
stmt2 = 'SELECT ' + geo_col + '.STGeometryN(1).ToString()' + ' FROM ' + table
else:
stmt2 = 'SELECT ' + geo_col + '.STGeometryN(1).ToString()' + ' FROM ' + table + ' WHERE ' + str([where_col]).replace('\'', '"')[1:-1] + ' IN (' + str(where_val)[1:-1] + ')'
df2 = read_sql(stmt2, conn)
df2.columns = ['geometry']
geometry = [loads(x) for x in df2.geometry]
df = GeoDataFrame(df, geometry=geometry, crs={'init' :'epsg:' + str(epsg)})
if export:
df.to_csv(path, index=False)
conn.close()
return(df)
编辑:使函数自动查找存在的几何字段。
喜欢这个功能,感谢 Dryden 提供的功能,但是提取几何体的代码在多多边形字段方面存在问题。如果其中一条记录的几何形状是多面体,并且您使用 .STGeometryN(1) 代码,那么您只会获得记录中可能存在的多个多边形中的第一个。地理数据框不会以 record.ID 的总几何结束,您调整代码并删除它应该处理多边形的 .STGeometryN(1)。
我用它来提取我存储在 SQL 服务器中的人口普查块组,并进行了一些调整(应该包括数据库模式参数)我让它工作但我会警告其他人使用它作为是确保您首先在 SQL 中使用此查询知道您的数据中是否有多面体。
select geometrycolumn.STGeometryType(),
,geometrycolumn.STNumGeometries()
from yourtable
order by 1
这会告诉您是否有多个多边形以及每条记录有多少个。
老问题,但如果有人登陆这里,这是另一个解决方案。
如果您确保 return 几何图形作为 WKB(即 [geoField].STAsBinary() AS geometry
),您可以使用 shapely.wkb.loads
函数
import pandas as pd
import geopandas as gpd
from shapely.wkb import loads
# define your connection, pymmssql, sqlAlchemy, pyodbc whatever
cnxn = DEFINE_CONNECTION
query = """SELECT [field1]
,[geoField].STAsBinary() AS geometry
,[someOtherFieldYouWant]
FROM [database].[dbo].[table]
"""
df = pd.read_sql(query, cnxn)
gdf = gpd.GeoDataFrame(df)
gdf.loc[:,'geometry'] = gdf.loc[:,'geometry'].apply(loads)
gdf = gdf.set_crs(4326) # OR whatever your CRS is
您可以从 table 中的几何图形的 SRID 中获取 CRS(这假设它们都是相同的,不知道它们是否必须如此)。
query = """SELECT TOP 1 [geoField].STSrid
FROM [database].[dbo].[table]"""
EPSG_AS_INT = pd.read_sql(query, cnxn).squeeze()
然后 gdf = gdf.set_crs(EPSG_AS_INT)