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.