Answers:
如果您在rgdal软件包中具有PostGIS驱动程序功能,那么仅是创建连接字符串并使用它的问题。在这里,我gis
使用默认凭据连接到本地数据库,因此我的DSN非常简单。您可能需要添加主机,用户名或密码。有关信息,请参见gdal文档。
> require(rgdal)
> dsn="PG:dbname='gis'"
该数据库中有哪些表?
> ogrListLayers(dsn)
[1] "ccsm_polygons" "nongp" "WrldTZA"
[4] "nongpritalin" "ritalinmerge" "metforminmergev"
得到一个:
> polys = readOGR(dsn="PG:dbname='gis'","ccsm_polygons")
OGR data source with driver: PostgreSQL
Source: "PG:dbname='gis'", layer: "ccsm_polygons"
with 32768 features and 4 fields
Feature type: wkbMultiPolygon with 2 dimensions
我有什么?
> summary(polys)
Object of class SpatialPolygonsDataFrame
Coordinates:
min max
x -179.2969 180.7031
y -90.0000 90.0000
Is projected: NA
proj4string : [NA]
Data attributes:
area perimeter ccsm_polys ccsm_pol_1
Min. :1.000 Min. :5.000 Min. : 2 Min. : 1
1st Qu.:1.000 1st Qu.:5.000 1st Qu.: 8194 1st Qu.: 8193
Median :1.000 Median :5.000 Median :16386 Median :16384
Mean :1.016 Mean :5.016 Mean :16386 Mean :16384
3rd Qu.:1.000 3rd Qu.:5.000 3rd Qu.:24577 3rd Qu.:24576
Max. :2.000 Max. :6.000 Max. :32769 Max. :32768
否则,您可以使用R的数据库功能并直接查询表。
> require(RPostgreSQL)
Loading required package: RPostgreSQL
Loading required package: DBI
> m <- dbDriver("PostgreSQL")
> con <- dbConnect(m, dbname="gis")
> q="SELECT ST_AsText(the_geom) AS geom from ccsm_polygons LIMIT 10;"
> rs = dbSendQuery(con,q)
> df = fetch(rs,n=-1)
这将返回中的要素几何df$geom
,您需要将其转换为sp
类对象(SpatialPolygons,SpatialPoints,SpatialLines)才能执行任何操作。rgeos中的readWKT函数可以帮助实现这一点。
要提防的事情通常是诸如数据库列之类的东西,它们无法映射到R数据类型。您可以在查询中包含SQL以进行转换,过滤或限制。不过,这应该可以帮助您入门。
readOGR
方法中是否可以使用sql代替完整表?
where
子句并通过传递给OGRsetAttributeFilter
但是所有操作都必须使用C和C ++代码完成...
如果Postgis中有数据,请不要将其导出到shapefile。从我的角度来看,这有点退一步。
您可以使用SQL语句从R中查询postgis数据库,并将其作为数据框导入,并且由于您熟悉R,因此可以从那里进行所需的所有地统计。我相信您也可以将地统计结果导出回postgis。
通过将SQL与Postgis函数配合使用,您还可以进行各种空间分析,例如覆盖操作,距离等。
对于地图绘图,我将使用QGIS(一种开放源GIS软件),它可以直接读取postgis(据我所知,这是该项目的最初目标),并且即将发布的2.0版具有许多功能,可以生成精美的地图。
新引入的sf-package(sp的继承者)提供st_read()
和st_read_db()
功能。在学习完本教程之后,以我的经验,它比已经提到的方法要快。由于SF可能有一天会取代SP,因此现在来看是个好消息;)
require(sf)
dsn = "PG:dbname='dbname' host='host' port='port' user='user' password='pw'"
st_read(dsn, "schema.table")
您还可以使用RPostgreSQL访问数据库:
require(sf)
require(RPostgreSQL)
drv <- dbDriver("PostgreSQL")
con <- dbConnect(drv, dbname = dbname, user = user, host = host, port = port, password = pw)
st_read_db(con, table = c("schema", "table"))
# or:
st_read_db(con, query = "SELECT * FROM schema.table")
dbDisconnect(con)
dbUnloadDriver(drv)
有了st_write()
您就可以上传数据。
您可以根据解决方案的每个步骤同时使用所有工具。
如果您可以从问题中提供更多详细信息,我们可以为您提供更具体的答案
我还将结合使用rgdal和RPostgreSQL。因此,与@Guillaume相同的代码,除了使用tryCatch处理更多行,伪随机表名称以及使用未记录表以提高性能外。(请注意:我们不能使用TEMP表,因为它不能从readOGR中看到)
dbGetSp <- function(dbInfo,query) {
if(!require('rgdal')|!require(RPostgreSQL))stop('missing rgdal or RPostgreSQL')
d <- dbInfo
tmpTbl <- sprintf('tmp_table_%s',round(runif(1)*1e5))
dsn <- sprintf("PG:dbname='%s' host='%s' port='%s' user='%s' password='%s'",
d$dbname,d$host,d$port,d$user,d$password
)
drv <- dbDriver("PostgreSQL")
con <- dbConnect(drv, dbname=d$dbname, host=d$host, port=d$port,user=d$user, password=d$password)
tryCatch({
sql <- sprintf("CREATE UNLOGGED TABLE %s AS %s",tmpTbl,query)
res <- dbSendQuery(con,sql)
nr <- dbGetInfo(res)$rowsAffected
if(nr<1){
warning('There is no feature returned.');
return()
}
sql <- sprintf("SELECT f_geometry_column from geometry_columns WHERE f_table_name='%s'",tmpTbl)
geo <- dbGetQuery(con,sql)
if(length(geo)>1){
tname <- sprintf("%s(%s)",tmpTbl,geo$f_geometry_column[1])
}else{
tname <- tmpTbl;
}
out <- readOGR(dsn,tname)
return(out)
},finally={
sql <- sprintf("DROP TABLE %s",tmpTbl)
dbSendQuery(con,sql)
dbClearResult(dbListResults(con)[[1]])
dbDisconnect(con)
})
}
用法:
d=list(host='localhost', dbname='spatial_db', port='5432', user='myusername', password='mypassword')
spatialObj<-dbGetSp(dbInfo=d,"SELECT * FROM spatial_table")
但是,这仍然非常缓慢:
对于一小组多边形(6个要素,22个字段):
后期部分:
user system elapsed
0.001 0.000 0.008
readOGR部分:
user system elapsed
0.313 0.021 1.436
您也可以结合使用rgdal和RPostreSQL。该示例函数使用RPostgreSQL创建一个临时表,并将其发送到readOGR以输出空间对象。这确实是低效且丑陋的,但效果很好。请注意,查询必须是SELECT查询,并且用户需要对数据库具有写权限。
RPostGIS <- function(coninfo,query) {
dsn=paste("PG:dbname='",coninfo$dbname,"' host='",coninfo$host,"' port='",coninfo$port,"' user='",coninfo$user,"' password='",coninfo$password,"'", sep='')
drv <- dbDriver("PostgreSQL")
con <- dbConnect(drv, user=coninfo$user, password=coninfo$password, dbname=coninfo$dbname)
res <- dbSendQuery(con,paste('CREATE TABLE tmp1209341251dva1 AS ',query,sep=''))
geo <- dbGetQuery(con,"SELECT f_geometry_column from geometry_columns WHERE f_table_name='tmp1209341251dva1'")
if(length(geo)>1){
tname=paste("tmp1209341251dva1(",geo$f_geometry_column[1],")")
}else{
tname="tmp1209341251dva1";
}
out <- tryCatch(readOGR(dsn,tname), finally=dbSendQuery(con,'DROP TABLE tmp1209341251dva1'))
dbDisconnect(con)
return(out)
}
您可以使用类似以下内容的名称进行调用:
> require('rgdal')
> require('RPostgreSQL')
> coninfo=list(host='localhost',dbname='spatial_db',port='5432',user='myusername',password='mypassword')
> spatial_obj<-RPostGIS(coninfo,"SELECT * FROM spatial_table")
如果以“ ST_AsText(geom)as geomwkt”返回查询并将结果提取到数据中,则可以使用:
library(rgeos);library(sp)
wkt_to_sp <- function(data) {
#data is data.frame from postgis with geomwkt as only geom
SpP <- SpatialPolygons(lapply(1:length(data$geomwkt),
function(x) Polygons(list(Polygon(readWKT(data$geomwkt[x]))),x)))
data <- data[,!(names(data) == "geomwkt")]
return(SpatialPolygonsDataFrame(SpP, data))
}
仍然非常缓慢。...测试1秒,持续100个几何。
Geotuple- https://github.com/rhansson/geotuple 是一个Web应用程序,用于连接R-Server和PostGIS(使用RPostgreSQL)
rgadl
?我在Ubuntu 13.04中...