답변:
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
조항 을 추가하고이를 통해 OGR에 전달하는 것이 간단 해 보이지만 setAttributeFilter
모두 C 및 C ++ 코드에서 수행되어야합니다.
Postgis에 데이터가 있으면 shapefile로 내 보내지 마십시오. 내 관점에서 볼 때, 그것은 조금 뒤로 물러납니다.
SQL 문을 사용하여 R에서 postgis 데이터베이스를 쿼리하고이를 데이터 프레임으로 가져오고 R에 익숙하므로 필요한 모든 지리 통계를 수행 할 수 있습니다. 지형 통계 결과를 postgis로 다시 내보낼 수도 있다고 생각합니다.
Postgis 함수와 함께 SQL을 사용하면 오버레이 작업, 거리 등과 같은 모든 종류의 공간 분석을 수행 할 수도 있습니다.
맵 플로팅 에는 postgis를 직접 읽을 수있는 OpenSource GIS 소프트웨어 인 QGIS를 사용 하고 (프로젝트의 초기 목표 인 것으로 알고있는 한) 곧 버전 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을 사용하여 DB에 액세스 할 수도 있습니다.
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과 동일한 코드입니다. (나 자신에게주의 : 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 개의 필드) :
postgis 부분 :
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)을 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))
}
여전히 고통스럽게 느리게 .... 테스트에서 100 개의 기하학에 대해 1 초.
rgadl
합니까? 우분투 13.04에 있습니다.