J'ai calculé la surface des distributions d'espèces (fusion de polygones à partir de fichiers de formes), mais comme cette zone peut être composée de polygones assez éloignés, je voudrais calculer une certaine mesure de dispersion. Ce que j'ai fait jusqu'à présent est de récupérer les centroïdes de chaque polygone, de calculer la distance entre ceux-ci et de les utiliser pour calculer le coefficient de variation, comme dans l'exemple factice ci-dessous;
require(sp)
require(ggplot2)
require(mapdata)
require(gridExtra)
require(scales)
require(rgeos)
require(spatstat)
# Create the coordinates for 3 squares
ls.coords <- list()
ls.coords <- list()
ls.coords[[1]] <- c(15.7, 42.3, # a list of coordinates
16.7, 42.3,
16.7, 41.6,
15.7, 41.6,
15.7, 42.3)
ls.coords[[2]] <- ls.coords[[1]]+0.5 # use simple offset
ls.coords[[3]] <- c(13.8, 45.4, # a list of coordinates
15.6, 45.4,
15.6, 43.7,
13.8, 43.7,
13.8, 45.4)
# Prepare lists to receive the sp objects and data frames
ls.polys <- list()
ls.sp.polys <- list()
for (ii in seq_along(ls.coords)) {
crs.args <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
my.rows <- length(ls.coords[[ii]])/2
# create matrix of pairs
my.coords <- matrix(ls.coords[[ii]],nrow = my.rows,ncol = 2,byrow = TRUE)
# now build sp objects from scratch...
poly = Polygon(my.coords)
# layer by layer...
polys = Polygons(list(poly),1)
spolys = SpatialPolygons(list(polys))
# projection is important
proj4string(spolys) <- crs.args
# Now save sp objects for later use
ls.sp.polys[[ii]] <- spolys
# Then create data frames for ggplot()
poly.df <- fortify(spolys)
poly.df$id <- ii
ls.polys[[ii]] <- poly.df
}
# Convert the list of polygons to a list of owins
w <- lapply(ls.sp.polys, as.owin)
# Calculate the centroids and get the output to a matrix
centroid <- lapply(w, centroid.owin)
centroid <- lapply(centroid, rbind)
centroid <- lapply(centroid, function(x) rbind(unlist(x)))
centroid <- do.call('rbind', centroid)
# Create a new df and use fortify for ggplot
centroid_df <- fortify(as.data.frame(centroid))
# Add a group column
centroid_df$V3 <- rownames(centroid_df)
ggplot(data = italy, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "grey50") +
# Constrain the scale to 'zoom in'
coord_cartesian(xlim = c(13, 19), ylim = c(41, 46)) +
geom_polygon(data = ls.polys[[1]], aes(x = long, y = lat, group = group), fill = alpha("red", 0.3)) +
geom_polygon(data = ls.polys[[2]], aes(x = long, y = lat, group = group), fill = alpha("green", 0.3)) +
geom_polygon(data = ls.polys[[3]], aes(x = long, y = lat, group = group), fill = alpha("lightblue", 0.8)) +
coord_equal() +
# Plot the centroids
geom_point(data=centroid_points, aes(x = V1, y = V2, group = V3))
# Calculate the centroid distances using spDists {sp}
centroid_dists <- spDists(x=centroid, y=centroid, longlat=TRUE)
centroid_dists
[,1] [,2] [,3]
[1,] 0.00000 69.16756 313.2383
[2,] 69.16756 0.00000 283.7120
[3,] 313.23834 283.71202 0.0000
# Calculate the coefficient of variation as a measure of polygon dispersion
cv <- sd(centroid_dist)/mean(centroid_dist)
[1] 0.9835782
Tracé des trois polygones et de leurs centroïdes
Je ne sais pas si cette approche est très utile car dans de nombreux cas, certains des polygones (comme le bleu dans l'exemple ci-dessus) sont assez grands par rapport aux autres, augmentant ainsi encore plus la distance. Par exemple, le centroïde de l'Australie a presque la même distance à ses frontières occidentales qu'à Papau.
Ce que j'aimerais obtenir, c'est un apport sur des approches alternatives. Par exemple, comment ou avec quelle fonction puis-je calculer la distance entre les polygones?
J'ai testé pour convertir le cadre de données SpatialPolygon ci-dessus en PointPatterns (ppp) {spatstat}
pour pouvoir exécuter nndist() {spatstat}
pour calculer la distance entre tous les points. Mais étant donné que je traite de zones assez étendues (beaucoup de polygones et de grandes), la matrice devient énorme et je ne sais pas comment continuer à atteindre la distance minimale entre les polygones .
J'ai également regardé la fonction gDistance {rgeos}
, mais je pense que cela ne fonctionne que sur des données projetées qui peuvent être un problème pour moi car mes zones peuvent en traverser plusieurs EPSG areas
. Le même problème se poserait pour la fonction crossdist {spatstat}
.
postgres/postgis
en plus deR
? J'ai utilisé un flux de travail dans lequel j'exécute la majorité de mon travailR
, mais stocke les données dans une base de données à laquelle j'accède à l'aidesqldf
. Cela vous permet d'utiliser toutes lespostgis
fonctions (dont la distance entre les polygones est simple)postgres
mais j'ai arrêté quand je ne savais pas (ne regardais pas) comment connecter le workflow / géostats entre la base de données etR
...Réponses:
Vous pouvez faire cette analyse dans le package "spdep". Dans les fonctions voisines pertinentes, si vous utilisez "longlat = TRUE", la fonction calcule la distance du grand cercle et renvoie les kilomètres comme unité de distance. Dans l'exemple ci-dessous, vous pouvez contraindre l'objet de liste de distances résultant ("dist.list") à une matrice ou à data.frame, cependant, il est assez efficace de calculer des statistiques récapitulatives à l'aide de lapply.
la source
spdeb
paquet. Juste pour clarifier, cette approche donne le même résultat que dans mon exemple, non?