태그 보관물: postgresql

postgresql

R에서 PostGIS 데이터로 작업합니까? R과 함께 일하고 있으며 이제는

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

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

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

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


답변

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에 데이터가 있으면 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()당신 과 함께 데이터를 업로드 할 수 있습니다.


답변

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

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

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


답변

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

답변

이제 SQL 쿼리를 통해 PostGIS 지오메트리 를 R로 가져올 수 있는 RPostGIS 패키지가 있습니다.


답변

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