28 votos

Extracción de áreas de intersección en R

Tengo dos polígonos. Uno contiene campos (X,Y,Z) y el otro contiene tipos de suelo (A,B,C,D). Quiero saber qué zona de cada campo contiene qué tipo de suelo. He intentado lo siguiente:

enter image description here

library(rgdal)
library(rgeos)
Field<-readOGR("./","Field")
Soil<-readOGR("./","Soil")
Results<-gIntersects(Soil,Field,byid=TRUE)
rownames(Results)<-Field@data$FieldName
colnames(Results)<-Soil@data$SoilType

> Results
      A     B     C     D
Z  TRUE FALSE FALSE FALSE
Y FALSE  TRUE  TRUE FALSE
X  TRUE  TRUE  TRUE  TRUE

y he obtenido buenos resultados al indicarme qué campo contiene qué tipo de suelo. Sin embargo, ¿cómo puedo obtener el área en su lugar?

2 votos

Como nota, st_intersection no funcionará si tus puntos son latitudes y longitudes. Usted no especificó que tenía coordenadas geográficas, aunque se insinúa ya que está hablando de tipos de suelo.

34voto

Matt SM Puntos 440

He aquí un enfoque alternativo utilizando el nuevo sf que sustituirá al paquete sp . Todo está mucho más limpio y es más fácil de usar:

library(sf)
library(tidyverse)

# example data from raster package
soil <- st_read(system.file("external/lux.shp", package="raster")) %>% 
  # add in some fake soil type data
  mutate(soil = LETTERS[c(1:6,1:6)]) %>% 
  select(soil)

# field polygons
field <- c("POLYGON((6 49.75,6 50,6.4 50,6.4 49.75,6 49.75))",
        "POLYGON((5.8 49.5,5.8 49.7,6.2 49.7,6.2 49.5,5.8 49.5))") %>% 
  st_as_sfc(crs = st_crs(soil)) %>% 
  st_sf(field = c('x','y'), geoms = ., stringsAsFactors = FALSE)

# intersect - note that sf is intelligent with attribute data!
pi <- st_intersection(soil, field)
plot(soil$geometry, axes = TRUE)
plot(field$geoms, add = TRUE)
plot(pi$geometry, add = TRUE, col = 'red')

# add in areas in m2
attArea <- pi %>% 
  mutate(area = st_area(.) %>% as.numeric())

# for each field, get area per soil type
attArea %>% 
  as_tibble() %>% 
  group_by(field, soil) %>% 
  summarize(area = sum(area))

enter image description here

   field  soil      area
   <chr> <chr>     <dbl>
1      x     A  24572264
2      x     B 209573036
3      x     C   5714943
4      x     D  76200409
5      x     E  31015469
6      x     F 234120314
7      y     B   2973232
8      y     C 175275520
9      y     D 188656204
10     y     E 153822938
11     y     F  11826698

29voto

Matt SM Puntos 440

Este método utiliza el intersect() de la función raster paquete. Los datos de ejemplo que he utilizado no son ideales (para empezar, están en coordenadas no proyectadas), pero creo que se entiende la idea.

library(sp)
library(raster)
library(rgdal)
library(rgeos)
library(maptools)

# Example data from raster package
p1 <- shapefile(system.file("external/lux.shp", package="raster"))
# Remove attribute data
p1 <- as(p1, 'SpatialPolygons')
# Add in some fake soil type data
soil <- SpatialPolygonsDataFrame(p1, data.frame(soil=LETTERS[1:12]), match.ID=F)

# Field polygons
p2 <- union(as(extent(6, 6.4, 49.75, 50), 'SpatialPolygons'),
             as(extent(5.8, 6.2, 49.5, 49.7), 'SpatialPolygons'))
field <- SpatialPolygonsDataFrame(p2, data.frame(field=c('x','y')), match.ID=F)
projection(field) <- projection(soil)

# intersect from raster package
pi <- intersect(soil, field)
plot(soil, axes=T); plot(field, add=T); plot(pi, add=T, col='red')

# Extract areas from polygon objects then attach as attribute
pi$area <- area(pi) / 1000000

# For each field, get area per soil type
aggregate(area~field + soil, data=pi, FUN=sum)

Imgur

Resultados:

    field soil         area
1      x    A 2.457226e+01
2      x    B 2.095659e+02
3      x    C 5.714943e+00
4      y    C 5.311882e-03
5      x    D 7.620041e+01
6      x    E 3.101547e+01
7      x    F 1.019455e+02
8      x    H 7.106824e-03
9      y    H 2.973232e+00
10     y    I 1.752702e+02
11     y    J 1.886562e+02
12     y    K 1.538229e+02
13     x    L 1.321748e+02
14     y    L 1.182670e+01

2 votos

Para aclarar: prefiero raster::intersect en rgeos::gIntersection porque el primero une los datos de atributos de los dos SpatialPolgonsDataFrame mientras que este último parece eliminar los datos de los atributos.

0 votos

Gracias por los muchos detalles y la respuesta correcta. ¡¡¡Me has ayudado mucho!!!

4 votos

Si se utiliza byid=TRUE en "gIntersection" devolverá el atributo IDS que puede utilizarse con merge para asociar los atributos. Las funciones son diferentes y debe tenerse en cuenta cómo. La función "intersect" utiliza las extensiones superpuestas, mientras que "gIntersection" es la intersección explícita de las geometrías vectoriales. El enfoque de intersección es una intersección cuadrada/rectangular y no una intersección de los polígonos reales. La extensión puede redefinirse utilizando extent y bbox. Ambos enfoques tienen sus ventajas.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X