R에서 PostGIS 데이터로 작업합니까?


27

나는 거의 항상 R과 함께 일하고 있으며 이제는 공간 데이터 마이닝을 위해 그것을 사용하고 있습니다.

GIS 데이터가있는 PostGIS 데이터베이스가 있습니다.

통계적 공간 분석 및 플롯 맵을 만들고 싶다면 다음을 수행하는 것이 좋습니다.

  • 테이블을 shapefile로 내보내거나;
  • 데이터베이스에 직접 작업 하시겠습니까?

답변:


34

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을 포함시켜 변환, 필터링 또는 제한을 수행 할 수 있습니다. 그래도 시작해야합니다.


좋은 대답이지만 어떻게 기능 (Postgis 드라이버)을 활성화 rgadl합니까? 우분투 13.04에 있습니다.
nanounanue

당신은 그것을 가지고 있습니까? ogrDrivers () 함수는 어딘가에 알려줄 것입니다. 그렇지 않다면 그것은 완전히 다른 질문입니다 (아마도 가장 먼저 googled 한 다음 R-sig-geo에 대해 질문했습니다)
Spacedman

우분투에서는 드라이버가 기본적으로 설치됩니다. MacOS X의 경우는 그렇지 않습니다. 감사합니다!
nanounanue

위의 코드에서 readOGR메서드에서 전체 테이블 대신 SQL을 사용할 수 있습니까?
nanounanue

현재는 생각하지 않습니다. 약 2.5 년 전에 r-sig-geo에 약간의 대화가 있었지만 아무것도 수행되지 않은 것 같습니다. where조항 을 추가하고이를 통해 OGR에 전달하는 것이 간단 해 보이지만 setAttributeFilter모두 C 및 C ++ 코드에서 수행되어야합니다.
Spacedman

8

Postgis에 데이터가 있으면 shapefile로 내 보내지 마십시오. 내 관점에서 볼 때, 그것은 조금 뒤로 물러납니다.

SQL 문을 사용하여 R에서 postgis 데이터베이스를 쿼리하고이를 데이터 프레임으로 가져오고 R에 익숙하므로 필요한 모든 지리 통계를 수행 할 수 있습니다. 지형 통계 결과를 postgis로 다시 내보낼 수도 있다고 생각합니다.

Postgis 함수와 함께 SQL을 사용하면 오버레이 작업, 거리 등과 같은 모든 종류의 공간 분석을 수행 할 수도 있습니다.

맵 플로팅 에는 postgis를 직접 읽을 수있는 OpenSource GIS 소프트웨어 인 QGIS를 사용 하고 (프로젝트의 초기 목표 인 것으로 알고있는 한) 곧 버전 2.0에는 멋진 맵 을 생성하는 많은 기능이 포함되어 있습니다 .


좋은 조언이지만 QGis로가는 R (플롯 포함)의 모든 것을 자동화하고 싶기 때문에 흐름을 깨뜨리지 않습니까?
nanounanue

이 경우 편한 경우 R을 사용하여지도를 그립니다. 그럼에도 불구하고 qgis 프로젝트 레이아웃을 postgis (업데이트 된) 데이터를 기반으로 준비하면 업데이트됩니다. 결국에는 R 또는 QGIS를 사용할지 여부는 개인적인 선택이 될 것입니다.
Alexandre Neto

빠른 응답에 감사하지만 Postgis의 테이블에서 R을 사용하여 플롯을 어떻게 만들 수 있습니까?
nanounanue

나는 R에 익숙하지 않고 그것을 사용하여 벡터 데이터를 어떻게 플롯 할 것인지 모르겠다 (QGIS를 사용한다고 말한 것처럼) 어떻게 R에서 shapfile을 플롯합니까? RI에서 PostgresSQL에 연결하기 위해 RPostgreSQL 을 사용 했습니다 . 나는 rgdal 이라고 생각 한다. 행운을 빕니다!
Alexandre Neto

5

새로 도입 된 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()당신 과 함께 데이터를 업로드 할 수 있습니다.


1
이것은 가장 간단한 해결책이며, sf
Cedric

2

솔루션의 각 단계에 따라 모든 도구를 동시에 사용할 수 있습니다.

  • 지구 정적 분석을 수행하려면 R을 사용하십시오. R의 패키지는 더욱 강력하며보다 분석적인 결과를 얻을 수 있습니다. SQL 쿼리를 기반으로 데이터를 가져올 수 있습니다.
  • 논리적으로 데이터를 집계하려는 경우 PostGIS를 사용할 수 있습니다. 규정 된 한도 내에있는 점과 같은 복잡한 쿼리에 대답 할 수 있습니까? 그러나 대규모로.
  • 매핑을 위해 R 또는 QGIS를 사용할 수 있습니다. QGIS는보다 직관적이며 R을 사용하면 원하는 결과를 얻기 위해 어려움을 겪을 수 있습니다.

문제에 대한 자세한 내용을 알려 주시면보다 구체적인 답변을 제공해 드리겠습니다.


마지막 포인트의 예를 제공해 주시겠습니까? Postgis의 테이블에서 R을 사용하여 맵을 그리려면 어떻게해야합니까?
nanounanue

@nanounanue 반드시 : library ( "rgdal") mydata = readOGR (dsn = "PG : dbname = <mydb>", layer = "schema.table") plot (mydata, axes = TRUE) title ( "My Plot").
nickves

이 페이지를 보라 : wiki.intamap.org/index.php/PostGIS
nickves '

2

또한 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


1

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")

0

'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 초.


0

Geotuple- https: //github.com/rhansson/geotuple 은 R-Server와 PostGIS를 연결하는 웹 앱입니다 (RPostgreSQL 사용).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.