Я извлекаю площадь и процент покрытия различных типов землепользования из растра, основанного на нескольких тысячах границ полигонов. Я обнаружил, что функция извлечения работает намного быстрее, если я перебираю каждый отдельный многоугольник и обрезаю, а затем маскирую растр до размера определенного многоугольника. Тем не менее, это довольно медленно, и мне интересно, есть ли у кого-нибудь предложения по повышению эффективности и скорости моего кода.
Единственное, что я нашел в связи с этим, - это ответ Роджера Биванда, который предложил использовать 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
Параллельная обработка
Параллельная обработка сократила время пользователя вдвое, но свела на нет преимущество, удвоив системное время. Растр использует это для функции извлечения, но, к сожалению, не для функции обрезки или маски. К сожалению, из-за «ожидания» с помощью «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
Ответы:
Я наконец-то дошел до улучшения этой функции. Я обнаружил, что для моих целей он был быстрее всего
rasterize()
на полигоне и использовалgetValues()
вместоextract()
. Растеризация не намного быстрее, чем исходный код для табулирования растровых значений в маленьких полигонах, но она сияет, когда дело доходит до больших областей многоугольника, в которых были обрезаны большие растры и извлекались значения. Я также обнаружил, чтоgetValues()
намного быстрее, чемextract()
функция.Я также разобрался с использованием многоядерной обработки
foreach()
.Я надеюсь, что это полезно для других людей, которые хотят R-решение для извлечения растровых значений из наложения полигонов. Это похоже на «пересечение таблиц» в ArcGIS, которое у меня не получалось, возвращая пустые выходные данные после нескольких часов обработки, как этот пользователь.
Вот функция:
Поэтому, чтобы использовать его, настройте его так,
single@data$OWNER
чтобы оно соответствовало имени столбца вашего идентифицирующего многоугольника (угадайте, что могло быть встроено в функцию ...) и вставьте:источник
getValues
было намного быстрее, чемextract
кажется, не является действительным, потому что, если вы используете,extract
вам не нужно делатьcrop
иrasterize
(илиmask
). Код в оригинальном вопросе делает и то, и другое, что должно примерно удвоить время обработки.Ускорение извлечения растра (растрового стека) из точки, XY или Polygon
Отличный ответ Люк. Вы должны быть волшебником R! Вот очень незначительный трюк для упрощения вашего кода (в некоторых случаях может немного повысить производительность). Вы можете избежать некоторых операций, используя cellFromPolygon (или cellFromXY для точек), а затем обрезать и получить значения.
Извлечение данных многоугольника или точек из растровых стеков ------------------------
источник
Если потеря точности наложения не очень важна - при условии, что она точна с самого начала - обычно можно достичь гораздо более высоких скоростей зонального расчета, сначала преобразовав полигоны в растр. В
raster
пакете содержитсяzonal()
функция, которая должна хорошо работать для поставленной задачи. Однако вы всегда можете поднастроить две матрицы одного и того же измерения, используя стандартную индексацию. Если вам нужно поддерживать полигоны и вы не против программного обеспечения ГИС, QGIS на самом деле должен работать быстрее в зональной статистике, чем ArcGIS или ENVI-IDL.источник
Я также некоторое время боролся с этим, пытаясь вычислить долю площади классов земного покрова на карте сетки ~ 300 х 300 м в сетке ~ 1 км х 1 км. Последний был полигональным файлом. Я попробовал многоядерное решение, но оно все еще было слишком медленным для количества ячеек сетки. Вместо этого я:
Эта процедура выполняется довольно быстро и без проблем с памятью на моем компьютере, когда я попробовал ее на карте земного покрова с> 15-миллиметровыми ячейками сетки при 300 х 300 м.
Я предполагаю, что описанный выше подход также будет работать, если вы захотите объединить файл многоугольника с неправильными формами с растровыми данными. Возможно, можно объединить шаги 1 и 2, напрямую растеризовав файл полигона в сетку 300xx300, используя растеризацию (растр, вероятно, медленный) или gdal_rasterize. В моем случае мне также нужно было перепроектировать, поэтому я использовал gdalwarp для перепроектирования и дезагрегации одновременно.
источник
Мне приходится сталкиваться с этой же проблемой, чтобы извлечь значения внутри многоугольника из большой мозаики (50k x 50k). У моего многоугольника всего 4 очка. Самый быстрый метод, который я нашел, состоит в том, чтобы
crop
наложить мозаику на границу многоугольника, триангулировать многоугольник на 2 треугольника, а затем проверить наличие точек в треугольнике (самый быстрый алгоритм, который я нашел). Сравните сextract
функцией, время работы уменьшено с 20 с до 0,5 с. Однако функцияcrop
все еще требует около 2 с для каждого многоугольника.Извините, я не могу предоставить полный воспроизводимый пример. Коды R ниже не включают входные файлы.
Этот метод работает только для простых полигонов.
источник