RでPostGISデータを使用していますか?


27

私はほとんど常にRを使用しており、現在は空間データマイニングに使用しています。

(明らかに)GISデータを含むPostGISデータベースがあります。

統計的な空間分析とプロットマップを作成する場合は、次の方法をお勧めします。

  • テーブルをシェープファイルとしてエクスポートするか、
  • データベースに直接働きかけますか?

回答:


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$geomspクラスオブジェクト(SpatialPolygons、SpatialPoints、SpatialLines)に変換して必要な処理を行う必要があります。rgeosのreadWKT関数はこれを支援します。

注意すべきことは通常、Rデータ型にマップできないデータベース列のようなものです。クエリにSQLを含めて、変換、フィルタリング、または制限を行うことができます。しかし、これで開始できます。


素晴らしい答えですが、どのようにして機能(Postgisドライバー)を有効にしrgadlますか?私はUbuntu 13.04にいます...
nanounanue

あなたはそれを手に入れましたか?ogrDrivers()関数はどこかを教えてくれるはずです。そうでない場合、それはまったく別の質問です(おそらく最初に
グーグルで検索し

Ubuntuでは、ドライバーはデフォルトでインストールされます。MacOS Xではそうではありません。ありがとう!
nanounanue

上記のコードでは、readOGRメソッドでフルテーブルの代わりにSQLを使用することは可能ですか?
nanounanue

現在私はそうは思いません。これについてr-sig-geoで約2.5年前に何らかのおしゃべりがありましたが、何も行われていないようです。where節を追加してOGRに渡すことは簡単に見えますsetAttributeFilterが、すべてCおよびC ++コードで実行する必要があります...
Spacedman

8

Postgisにデータがある場合は、シェープファイルにエクスポートしないでください。私の観点からすると、それは一種の後退です。

SQLステートメントを使用してRからpostgisデータベースをクエリし、それらをデータフレームとしてインポートし、Rに精通しているため、そこから必要なすべての地球統計学を実行できます。地球統計の結果をpostgisにエクスポートして戻すこともできます。

Postgis関数でSQLを使用すると、オーバーレイ操作、距離など、あらゆる種類の空間分析も実行できます。

マッププロットには、PostGISを直接読み取ることができるオープンソースGISソフトウェアであるQGISを使用します(それがプロジェクトの最初の目標である限り)、今後のバージョン2.0には、見栄えの良いマップを作成するための多くの機能が含まれます


素晴らしいアドバイスはわかりましたが、Rのすべて(プロットを含む)をQGisに自動化したいので、フローを中断しませんか?
nanounanue

その場合、それに慣れていれば、Rを使用してマップをプロットするだけです。それでも、qgisプロジェクトのレイアウトをpostgis(更新済み)データに基づいて準備すると、それらも更新されます。最終的には、Rを使用するかQGISを使用するかは個人的な選択になると思います。
アレクサンドルネトー

迅速な対応に感謝しますが、PostgisのテーブルからRを使用してプロットを作成するにはどうすればよいですか?
nanounanue

私はRについてあまり経験がなく、それを使用してベクトルデータをプロットする方法がわかりません(そのためにQGISを使用すると言ったように)、どのようにRでshapfilesをプロットしますか?RIからPostgresSQLに接続するには、以前にRPostgreSQLを使用しました。rgdalと思います ]。がんばろう!
アレクサンドルネトー

5

新たに導入されたSF-パッケージ(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
これが最も簡単な解決策です。signの使用方法を説明するvignette cran.r-project.org/web/packages/sf/vignettes/sf2.htmlがあります
Cedric

2

ソリューションの各ステップに基づいて、すべてのツールを同時に使用できます。

  • 静力学解析を行いたい場合は、Rを使用してください。Rのパッケージはより堅牢であり、より解析的な結果が得られます。SQLクエリに基づいてデータをインポートできます。
  • 論理ベースに基づいてデータを集約する場合は、PostGISを使用できます。規定の範囲内にある多くのポイントのような複雑なクエリに答えることができますか?しかし、大規模に。
  • マッピングには、RまたはQGISを使用できます。QGISはより単純で、Rを使用すると目的の結果を得るのに苦労する場合があります。

問題の詳細をお知らせいただければ、より具体的な回答を提供できます。


最後のポイントの例を教えてもらえますか、つまり、PostgisのテーブルからRでマップをプロットしたい場合、どうすればいいですか?
nanounanue

@nanounanue sure:library( "rgdal")mydata = readOGR(dsn = "PG:dbname = <mydb>"、layer = "schema.table")plot(mydata、axes = TRUE)title( "My Plot")。
ニックス

このページもご覧ください:wiki.intamap.org/index.php/PostGIS
nickves

2

また、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フィールド)の場合:

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に送信します。これは本当に非効率的でandいですが、非常にうまく機能します。クエリは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)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))
}

それでも痛々しいほど遅い....テストで100ジオムに対して1秒。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.