将mssql空间字段导入geopandas / shapely geometry

时间:2016-10-11 06:36:06

标签: python sql-server shapely geopandas

我似乎无法直接将mssql空间字段导入geopandas。我可以使用Pymssql将普通的mssql表导入pandas而没有任何问题,但我无法想出一种方法将空间字段导入到匀称的几何体中。我知道mssql的OGR驱动程序应该能够处理它,但我在sql中不够熟练,无法解决这个问题。 这对于线和多边形来说更是一个问题,因为点可以从mssql字段转换为x和y坐标。 谢谢!

2 个答案:

答案 0 :(得分:1)

我通过正确查询sql数据库表并通过shapely.wkt中的loads函数将wkt字符串转换为匀称几何来解决这个问题。

我不是程序员,所以请记住功能的组织。该函数可以导入带有或不带有GIS几何的mssql表。

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)

编辑:使函数自动找到几何字段(如果存在)。

答案 1 :(得分:0)

喜欢此功能,并感谢Dryden的帮助,但是提取几何图形的代码存在多脂素场问题。如果其中一个记录的几何图形是一个多面体,并且您使用.STGeometryN(1)代码,则只会得到该记录中潜在多个面中的第一个。地理数据框不会以该记录的总几何图形结束。您需要对ID进行代码调整并删除应处理多面体的.STGeometryN(1)。

我用它来提取存储在SQL Server中的人口普查区块组,并进行了一些调整(应包括数据库架构参数),但是我会警告其他使用它的人,以确保您知道首先在SQL中使用此查询在数据中是否包含多边形。

select geometrycolumn.STGeometryType(), 
,geometrycolumn.STNumGeometries() 
 from yourtable
 order by 1

这将告诉您是否有多边形,每条记录有多少个。

对不起,主持人我想把它作为评论,因为它并不是对问题的真正回答,但是我的声誉目前尚不足以发表评论,我认为我的意见很重要。 (Stack Exchange-GIS声誉很高,可以发表评论-我的SO和SE代表不应该合并吗?或者应该将其张贴在GIS论坛上)