Як працює просторовий багатокутник% над% багатокутника при агрегуванні значень у r?


12

Я працюю над проектом екологічної епідеміології, де я зазнаю точкового опромінення (~ 2000 операцій з виробництвом свиней - IHO). Ці ІХО розпорошуються на прилеглих полях, але краплі води та калу та запаху можуть подолати милі. Таким чином, ці точкові експозиції отримують 3 мільйони буферів, і я хочу знати кількість експозицій IHO (різних видів - сума кількості гною, кількість свиней, що завгодно; найпростіше, просто кількість буферів, що перекриваються, для блоків перепису NC) (~ 200 000). Блоки перепису виключень (синій) - це (1) все, що знаходиться в топ-5 найбільш густонаселених міст та (2) графствах, які не межують з округом з IHO в ньому (зверніть увагу: це було зроблено за допомогою функції gRelate та кодів DE-9IM - дуже струнка!). Дивіться нижче зображення для наочності

введіть тут опис зображення

Останнім кроком є ​​агрегування буферизованого представлення експозиції до кожного блоку перепису. Ось де я наткнувся.

Я добре проживав із функціями% over% у пакеті sp досі, але з надмірної віньетки розумію, що полі-полі та полі-рядки реалізовані в rgeos. Віньєтка охоплює лише рядки-полі та полі-самопосилання на полі, а не з агрегуванням, тому я трохи заплутаний у тому, які мої варіанти є полі-полі з агрегацією функції, як сума чи середнє значення.

Для тестового випадку розглянемо дещо детальний фрагмент, який працює з файлом кордонів країн світу. Це потрібно мати можливість скопіювати та запустити так, як є, оскільки я використовую випадкове насіння для очок і оскільки завантажую та розпаковую світовий файл у коді.

Спочатку ми створюємо 100 балів, потім використовуємо функцію over з аргументом fn для додавання елемента в кадр даних. Тут є багато пунктів, але погляньте на Австралію: 3 бали, номер 3 як мітка. Все йде нормально.

введіть тут опис зображення

Тепер ми перетворюємо геометрії, щоб ми могли створювати буфери, перетворювати назад і відображати ці буфери. (Включено в попередню карту, оскільки я обмежений двома посиланнями.) Ми хочемо знати, скільки буферів перетинаються в кожній країні - в Австралії, очей, це 4. Я не можу за життя зрозуміти, що відбувається хоча отримати це з функцією over. Дивіться мою безладність спроби у заключних рядках коду.

EDIT: Зауважте, що коментатор на 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, яке було виправлено місяць тому, але ще не перетворило його на реліз CRAN. Далі йде обхід, якщо вас цікавить лише кількість перехресть:

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

Я використовую NROWтут замість того, lengthщоб він працював з неправильними rgeos (0,3-8, від CRAN), а також з виправленими (0,3-10, від r-forge). Рання пропозиція використання

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) Що таке помилка, яку я потрапляю сюди-rgeos :: over, повертає географію просторового полігону, а не просторовий кадр полі даних? Чи не деякі функції просто повертають кадри даних ...? (2) Як це, як правило, має працювати з агрегатом і більше? Я трохи розгублений щодо їх намічених відмінностей та випадків використання. Дуже вдячний за зважування, дякую. І сторонне: будь-які пропозиції щодо розуміння циклу випуску CRAN?
Майк Долан Фліс

Також щодо оригінального питання: мені потрібно порахувати кількість експозицій, але мені також дійсно потрібно підсумувати їх - такі речі, як кількість свиней у кожній експозиції. Підрахунок перекриттів - це початок ... але це звучить як рішення, яке мені потрібно, це втягнути новітні реггеси, так? Не обійтися без цього функціональної агрегації (не просто підрахунку)?
Майк Долан Фліс

(1) rgeos :: over для підпису SpatialPolygons,SpatialPolygonsDataFrameповинен повертати a data.frame, але повертає вектор індексу, ідентичний тому, коли yбув би SpatialPolygons. sp::aggregateробить те, що ви робите з над, більш зручним для користувача способом, повертаючи Spatialоб'єкт замість data.frame. Пакети CRAN підтримуються волонтерами.
Edzer Pebesma

Добре, дякую Едзер. Це здається, що сукупність покладається на rgeos більше, тому для того, щоб ця функціональність випереджала цикл випуску CRAN (коли це є), мені потрібно дізнатися, як завантажити найновіші rgeos і вирішити цю проблему. Дякую. І дякую за всю вашу роботу над пакунком !!
Майк Долан Фліс

Також, Edzer, дуже дякую за замітку про R-sis-geo. Не знав, де краще місце для публікації, тому я радий, що нитка зараз вказує тут.
Майк Долан Флісс

1

Я тим часом здійснив швидкий (і погано закодований) замінник, який створює потрібний мені кадр даних, оскільки на моє запитання не дуже відповіли вищезгадані рішення, що стосуються лише підрахунку, або "відпрацювати нові rgeos", які я Я не досить досвідчений, щоб зрозуміти, як це зробити.

Ця функція явно (1) неповна (зауважте, як я ігнорую аргумент fn) та (2) неефективна, оскільки я приходжу до неї без потужних маніпуляцій R / масиву / матриці ... (очевидно, я надходжу з інших мов без ця влада), але, чесно кажучи, я все ще плутаю те, що повертає структура функції 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.
Edzer Pebesma
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.