rの値を集計するとき、空間ポリゴン%over%ポリゴンはどのように機能しますか?


12

私は環境疫学プロジェクトに取り組んでおり、そこではポイント暴露(〜2,000の産業豚の操業-IHO)を受けています。これらのIHOは近くのフィールドにスプレーしますが、糞の水滴と臭いは何マイルも移動します。したがって、これらのポイント露出は3miのバッファを取得し、NCセンサスブロックごとのIHO露出の数(さまざまな種類の肥料の合計、豚の数、最も単純な、重複する露出バッファの数)を知りたい(〜200,000)。除外国勢調査ブロック(青)は、(1)最も人口の多い上位5都市のすべてであり、(2)IHOのある郡と国境を接していない郡(注:gRelate関数とDE-9IMコードで行われました-非常に滑らかです!)。下の画像をご覧ください

ここに画像の説明を入力してください

最後のステップは、バッファリングされた露出表現をすべての国勢調査ブロックに集約することです。ここで私は困惑しています。

これまで、spパッケージの%over%関数を使って楽しい時間を過ごしましたが、over-vignetteから、poly-polyとpoly-line overはrgeosで実装されていることを理解しています。ビネットはラインポリと自己参照ポリのみを対象とし、集計は対象外です。そのため、合計や平均などの関数集計を使用したポリポリのオプションについて少し混乱しています。

テストケースについては、以下の世界の国の国境ファイルで動作する多少冗長なスニペットを検討してください。これは、ポイントにランダムシードを使用しているため、またワールドファイルをコードでダウンロードして解凍しているため、そのままコピーして実行できるはずです。

最初に100ポイントを作成し、次に関数fnを引数に使用してデータフレーム内の要素を加算します。ここには多くのポイントがありますが、オーストラリアを見てください:3ポイント、ラベルとしての3番目。ここまでは順調ですね。

ここに画像の説明を入力してください

次に、ジオメトリを変換して、バッファを作成し、元に戻して、それらのバッファをマップできるようにします。(リンクは2つに制限されているため、前のマップに含まれています。)各国がオーバーラップしているバッファーの数を知りたいです。オーストラリアの場合、目で見て4です。ただし、over関数で取得します。コードの最終行で私の混乱を参照してください。

編集:r-sis-geoのコメンターが集約関数に言及していることに注意してください-スタック交換質問63577でも参照されています-そのため、回避策/フローはその関数を介している可能性がありますが、なぜ行く必要があるのか​​分かりませんポリポリを集約するために、他の空間オブジェクトにその機能があるように思えます。

require(maptools)
require(sp)
require(rgdal)
require(rgeos)

download.file("http://thematicmapping.org/downloads/TM_WORLD_BORDERS_SIMPL-0.3.zip", destfile="world.zip")
unzip("world.zip")
world.map = readOGR(dsn=".", "TM_WORLD_BORDERS_SIMPL-0.3", stringsAsFactors = F)
orig.world.map = world.map #hold the object, since I'm going to mess with it.

#Let's create 500 random lat/long points with a single value in the data frame: the number 1
set.seed(1)
n=100
lat.v = runif(n, -90, 90)
lon.v = runif(n, -180, 180)
coords.df = data.frame(lon.v, lat.v)
val.v = data.frame(rep(1,n))
names(val.v) = c("val")
names(coords.df) = c("lon", "lat")
points.spdf = SpatialPointsDataFrame(coords=coords.df, proj4string=CRS("+proj=longlat +datum=WGS84"), data=val.v)
points.spdf = spTransform(points.spdf, CRS(proj4string(world.map)))
plot(world.map, main="World map and points") #replot the map
plot(points.spdf, col="red", pch=20, cex=1, add=T) #...and add points.

#Let's use over with the point data
join.df = over(geometry(world.map), points.spdf,  fn=sum)
plot(world.map, main="World with sum of points, 750mi buffers") #Note - happens to be the count of points, but only b/c val=1.
plot(points.spdf, col="red", pch=20, cex=1, add=T) #...and add points.
world.map@data = data.frame(c(world.map@data, join.df))
#world.map@data = data.frame(c(world.map@data, over(world.map, points.spdf, fun="sum")))
invisible(text(getSpPPolygonsLabptSlots(world.map), labels=as.character(world.map$val), cex=1))
#Note I don't love making labels like above, and am open to better ways... plus I think it's deprecated/ing

#Now buffer...
pointbuff.spdf = gBuffer(spTransform(points.spdf, CRS("+init=EPSG:3358")), width=c(750*1609.344), byid=T)
pointbuff.spdf = spTransform(pointbuff.spdf, world.map@proj4string)
plot(pointbuff.spdf, col=NA, border="pink", add=T)



#Now over with the buffer (poly %over% poly).  How do I do this?
world.map = orig.world.map
join.df = data.frame(unname(over(geometry(world.map), pointbuff.spdf, fn=sum, returnList = F)) ) #Seems I need to unname this...?
names(join.df) = c("val")
world.map@data = data.frame(c(world.map@data, join.df)) #If I don't mess with the join.df, world.map's df is a mess..
plot(world.map, main="World map, points, buffers...and a mess of wrong counts") #replot the map
plot(points.spdf, col="red", pch=20, cex=1, add=T) #...and add points.
plot(pointbuff.spdf, col=NA, border="pink", add=T)
invisible(text(getSpPPolygonsLabptSlots(world.map), labels=as.character(world.map$val), cex=1)) 
#^ But if I do strip it of labels, it seems to be misassigning the results?
# Australia should now show 4 instead of 3.  I'm obviously super confused, probably about the structure of over poly-poly returns.  Help?

リダイレクトに感謝​​します-ここから削除して、そこに再投稿する必要がありますか?最高の動きは何ですか?ありがとう。
マイクドーランフリス

回答:


5

明確な質問と再現可能な例に感謝します。

あなたの理解は正しいです、そしてこれはrgeos :: overのバグに帰着します。これは修正されました 1か月前れましたが、まだCRANリリースには至っていません。交差点の数だけに関心がある場合の回避策は次のとおりです。

world.map$val = sapply(over(geometry(world.map), pointbuff.spdf, returnList = TRUE), NROW)

私はNROW代わりにここを使用していますlength、間違ったrgeos(CRANの0.3-8)と修正された(r-forgeの0.3-10)で動作するように、。使用の以前の提案

a = aggregate(pointbuff.spdf, world.map, sum)

交差点の数もカウントしますが、固定rgeosバージョンがインストールされている場合のみです。その利点は、より直感的な名前に加えて、直接返すことですSpatialのジオメトリを持つオブジェクトをですworld.map

rgeos 0.3-8を機能させるには、以下を追加します

setMethod("over",
    signature(x = "SpatialPolygons", y = "SpatialPolygonsDataFrame"),
        rgeos:::overGeomGeomDF)

を使用する前に、スクリプトに追加しますover


とても助かります、ありがとう。特に、修正前と修正後の両方で機能するソリューションを提供することを称賛したいと思います。(1)here-rgeos :: overに当たっているバグは何ですか?空間ポリゴンデータフレームではなく、空間ポリゴンジオグラフィを返していますか?一部の関数はデータフレームを返すだけではありませんか?(2)これが一般的にどのように集約以上で機能すると想定されていますか?私は彼らの意図した違いとユースケースに関して少し混乱しています。本当にありがとうございます。補足:CRANリリースサイクルを理解するための提案はありますか?
マイクドーランフリス

また、元の質問については、露出の数をカウントする必要がありますが、実際にはそれらを合計する必要があります-各露出の豚の数など。重複を数えることは始まりです...しかし、私が必要とする解決策は、最新のrgeosを取り込むことだと思われますか?それなしでその機能的な集計を行う方法はありません(単にカウントするだけではありません)?
マイクドーランフリス

(1)署名のrgeos :: overはSpatialPolygons,SpatialPolygonsDataFrameを返す必要data.frameがありますが、の場合yと同じインデックスベクトルを返しますSpatialPolygonssp::aggregateは、より使いやすい方法でoverを実行し、のSpatial代わりにオブジェクトを返しますdata.frame。CRANパッケージはボランティアによって管理されています。
エドザーペベスマ15年

はい、エドザーに感謝します。集合体はrgeosに依存しているように聞こえるので、この機能をCRANのリリースサイクルの前に(それがいつでも)得るためには、最新のrgeosをダウンロードして、それを解決する方法を見つける必要があります。ありがとうございました。そして、パッケージに関するすべての作業に感謝します!!
マイクドーランフリス

また、Edzer、R-sis-geoについてのメモをどうもありがとう。投稿するのに最適な場所がどこにあるのか確信が持てなかったので、スレッドがここを指すようになったことを嬉しく思います。
マイクドーランフリス

1

私の質問は上記のカウントのみの解決策や「新しいrgeosを解決する」では十分に答えられないので、必要なデータフレームを作成する間、迅速な(そしてコーディングが不十分な)過剰な置き換えをホイップしました。方法を理解するのに十分なスキルがありません。

この関数は明らかに(1)不完全です(fn引数を無視する方法に注意してください)および(2)非効率的です。Rの強力な配列操作/ sapplyがなくて...(明らかに、他の言語からその力)しかし、正直なところ、私はまだover関数の構造が返すもの(リストのリスト...?そしてNAの場合は空のリスト?)を混乱させています。価値のあるもの(編集歓迎)のために、この関数は必要な作業を正常に実行し、他の関数の動作を模倣します。

編集歓迎:

overhelper <- function(pol, pol.df, fn=sum, verbose=F){
   if(verbose) {cat("Building over geometry...\n"); t=Sys.time(); t}
   geolist = over(geometry(pol), pol.df, returnList = T)
   if(verbose) {cat("Geometry done. Aggregating df. \n"); Sys.time()-t;t=Sys.time();t;}
   results = data.frame(matrix(0,nrow=length(pol), ncol=ncol(pol.df)))
   names(results) = names(pol.df)
   end = length(geolist)

   for (i in 1:end){
     if(verbose) cat(i, "...")
     results[i,] = sapply(pol.df@data[unlist(geolist[i]),], fn)
   }
   if(verbose) cat("Aggregation done! (", Sys.time()-t, ") \n Returning result vector.")
   return (results)
}

1
私の答えにrgeos 0.3-8を修正する代替手段を追加しました。
エドザーペベスマ15年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.