Wyciągam obszar i procent pokrycia różnych rodzajów użytkowania gruntów z rastra opartego na kilku tysiącach granic wielokąta. Przekonałem się, że funkcja wyodrębniania działa znacznie szybciej, jeśli iteruję po każdym wielokącie i przycinam, a następnie maskuje raster do rozmiaru określonego wielokąta. Niemniej jednak jest dość powolny i zastanawiam się, czy ktoś ma jakieś sugestie dotyczące poprawy wydajności i szybkości mojego kodu.
Jedyne, co znalazłem w związku z tym, to odpowiedź Rogera Bivanda, który zasugerował użycie, GDAL.open()
a GDAL.close()
także getRasterTable()
i getRasterData()
. Przyjrzałem się tym, ale w przeszłości miałem problemy z Gdalem i nie znam go wystarczająco dobrze, aby wiedzieć, jak go wdrożyć.
Powtarzalny przykład:
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)
Jak dotąd najszybsza metoda
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
Przetwarzanie równoległe
Przetwarzanie równoległe skróciło czas użytkownika o połowę, ale podważyło korzyści wynikające z podwojenia czasu systemowego. Raster używa tego do funkcji wyodrębniania, ale niestety nie do funkcji przycinania lub maskowania. Niestety pozostawia to nieco więcej całkowitego czasu, który upłynął z powodu „oczekiwania” przez „IO”.
beginCluster( detectCores() -1) #use all but one core
uruchom kod na wielu rdzeniach:
user system elapsed
23.31 0.68 42.01
następnie zakończ klaster
endCluster()
Powolna metoda: alternatywna metoda wyodrębniania bezpośrednio z funkcji rastra zajmuje dużo więcej czasu i nie jestem pewien, czy zarządzanie danymi doprowadzi ją do żądanej formy:
system.time(ext<-extract(c,bound))
user system elapsed
1170.64 14.41 1186.14
Odpowiedzi:
W końcu udało mi się ulepszyć tę funkcję. Przekonałem się, że dla moich celów
rasterize()
najpierw był najszybszy do wielokąta i używał gogetValues()
zamiastextract()
. Rasteryzacja nie jest dużo szybsza niż oryginalny kod do zestawiania wartości rastrowych w małych wielokątach, ale świeci, gdy dojdzie do dużych obszarów wielokąta, które miały duże rastry do przycięcia i wyodrębnienia wartości. Odkryłem również, żegetValues()
był znacznie szybszy niżextract()
funkcja.Zorientowałem się również przy użyciu przetwarzania wielordzeniowego
foreach()
.Mam nadzieję, że jest to przydatne dla innych osób, które chcą rozwiązania R do wyodrębniania wartości rastrowych z nakładki wielokąta. Jest to podobne do „Przecięcia tabelarycznego” ArcGIS, które nie działało dla mnie dobrze, zwracając puste wyniki po godzinach przetwarzania, jak ten użytkownik.
Oto funkcja:
Aby go użyć, dostosuj,
single@data$OWNER
aby pasował do nazwy kolumny wielokąta identyfikacyjnego (zgadnij, że mogła zostać wbudowana w funkcję ...) i wstaw:źródło
getValues
była znacznie szybsza niżextract
ta, nie wydaje się ważna, ponieważ jeśli ją wykorzystaszextract
, nie musisz tego robićcrop
irasterize
(lubmask
). Kod w pierwotnym pytaniu spełnia obie te funkcje, co powinno wiązać się z podwójnym czasem przetwarzania.Przyspiesz wyodrębnianie rastra (stosu rastrowego) z punktu, XY lub wielokąta
Świetna odpowiedź Luke. Musisz być czarodziejem R. Oto bardzo drobna poprawka w celu uproszczenia kodu (w niektórych przypadkach może nieco poprawić wydajność). Możesz uniknąć niektórych operacji, używając cellFromPolygon (lub cellFromXY dla punktów), a następnie klip i getValues.
Wyodrębnij dane wielokątów lub punktów ze stosów rastrowych ------------------------
źródło
Jeśli utrata precyzji nakładki nie jest niezwykle ważna - zakładając, że jest ona precyzyjna na początku - zazwyczaj można osiągnąć znacznie większe prędkości obliczeniowe stref, najpierw przekształcając wielokąty w raster.
raster
Pakiet zawierazonal()
funkcję, która powinna działać dobrze dla zamierzonego zadania. Zawsze można jednak podzestawić dwie macierze tego samego wymiaru przy użyciu standardowego indeksowania. Jeśli musisz zachować wielokąty i nie przeszkadza ci oprogramowanie GIS, w rzeczywistości statystyki QGIS muszą być szybsze niż ArcGIS lub ENVI-IDL.źródło
Zmagałem się również z tym przez jakiś czas, próbując obliczyć udział w powierzchni klas pokrycia terenu na mapie o wymiarach ~ 300m x 300m na siatce o długości ~ 1 km x 1 km. Ten ostatni był plikiem wielokąta. Wypróbowałem rozwiązanie wielordzeniowe, ale wciąż było to zbyt wolne dla liczby komórek siatki, które miałem. Zamiast tego:
Ta procedura działa dość szybko i bez problemów z pamięcią na moim komputerze, gdy wypróbowałem ją na mapie pokrycia terenu z> 15 milionami komórek siatki o wymiarach 300m x 300m.
Zakładam, że powyższe podejście zadziała również, jeśli chcemy połączyć plik wielokąta o nieregularnych kształtach z danymi rastrowymi. Być może można połączyć krok 1 i 2, bezpośrednio rasteryzując plik wielokąta do siatki o wymiarach 300 x 300 za pomocą rasteryzacji (raster prawdopodobnie wolny) lub gdal_rasterize. W moim przypadku musiałem również ponownie wykonać rzut, więc użyłem gdalwarp zarówno do zmiany wyglądu, jak i do dezagregacji w tym samym czasie.
źródło
Muszę zmierzyć się z tym samym problemem, aby wyodrębnić wartości wewnątrz wielokąta z dużej mozaiki (50k x 50k). Mój wielokąt ma tylko 4 punkty. Najszybszą metodą, jaką znalazłem, jest
crop
mozaikowanie w ramach wieloboku, trójkątowanie wieloboku w 2 trójkąty, a następnie sprawdzanie, czy punkty w trójkącie (najszybszy algorytm, jaki znalazłem). W porównaniu zextract
funkcją czas pracy skraca się z 20 s do 0,5 s. Jednak funkcjacrop
nadal wymaga około 2 s dla każdego wielokąta.Niestety nie mogę podać pełnego odtwarzalnego przykładu. Poniższe kody R nie obejmują plików wejściowych.
Ta metoda działa tylko w przypadku prostych wielokątów.
źródło