数千のポリゴン境界に基づいて、さまざまな土地利用タイプの面積と被覆率をラスタから抽出しています。個々のポリゴンを繰り返し処理し、特定のポリゴンのサイズまでラスターをマスクして切り取ると、抽出機能がはるかに高速に動作することがわかりました。それにもかかわらず、それはかなり遅いです、そして、誰かが私のコードの効率と速度を改善するための提案を持っているかどうか疑問に思っています。
私はこれに関連した見つけた唯一のものです。この応答使うことを提案ロジャーBivandによるGDAL.open()
とGDAL.close()
だけでなく、getRasterTable()
とgetRasterData()
。私はそれらを調べましたが、過去にgdalに問題があり、それを実装する方法を知るのに十分なほどよく知りません。
再現可能な例:
library(maptools) ## For wrld_simpl
library(raster)
## Example SpatialPolygonsDataFrame
data(wrld_simpl) #polygon of world countries
bound <- wrld_simpl[1:25,] #name it this to subset to 25 countries and because my loop is set up with that variable
## Example RasterLayer
c <- raster(nrow=2e3, ncol=2e3, crs=proj4string(wrld_simpl), xmn=-180, xmx=180, ymn=-90, ymx=90)
c[] <- 1:length(c)
#plot, so you can see it
plot(c)
plot(bound, add=TRUE)
これまでで最速の方法
result <- data.frame() #empty result dataframe
system.time(
for (i in 1:nrow(bound)) { #this is the number of polygons to iterate through
single <- bound[i,] #selects a single polygon
clip1 <- crop(c, extent(single)) #crops the raster to the extent of the polygon, I do this first because it speeds the mask up
clip2 <- mask(clip1,single) #crops the raster to the polygon boundary
ext<-extract(clip2,single) #extracts data from the raster based on the polygon bound
tab<-lapply(ext,table) #makes a table of the extract output
s<-sum(tab[[1]]) #sums the table for percentage calculation
mat<- as.data.frame(tab)
mat2<- as.data.frame(tab[[1]]/s) #calculates percent
final<-cbind(single@data$NAME,mat,mat2$Freq) #combines into single dataframe
result<-rbind(final,result)
})
user system elapsed
39.39 0.11 39.52
並列処理
並列処理はユーザー時間を半分に削減しましたが、システム時間を2倍にすることで利点を無効にしました。Rasterはこれを抽出機能に使用しますが、残念ながらクロップまたはマスク機能には使用しません。残念ながら、これにより、「IO」による「待機」により、合計経過時間がわずかに長くなります。
beginCluster( detectCores() -1) #use all but one core
複数のコアでコードを実行します:
user system elapsed
23.31 0.68 42.01
その後、クラスターを終了します
endCluster()
遅い方法: ラスター関数から直接抽出を行う別の方法は、はるかに長い時間がかかり、データ管理がそれを希望する形式にするかどうかわかりません。
system.time(ext<-extract(c,bound))
user system elapsed
1170.64 14.41 1186.14