Tengo dos características espaciales:

library(sf)

points1 <- data.frame(foo = seq(15, 75, 15), 
                     long = c(-85, -80, -78, -75, -82), 
                     lat = c(34, 36, 37, 38, 35)) %>% 
    st_as_sf(coords = c('long', 'lat'), crs = 4326) 

points2 <- data.frame(bar = seq(15, 75, 15), 
                     long = c(85, 80, 78, 75, 82), 
                     lat = c(30, 32, 34, 36, 38)) %>% 
    st_as_sf(coords = c('long', 'lat'), crs = 4326) 

cbind(points1, points2) -> df

Esto da:

  foo bar       geometry    geometry.1
1  15  15 POINT (-85 34) POINT (85 30)
2  30  30 POINT (-80 36) POINT (80 32)
3  45  45 POINT (-78 37) POINT (78 34)
4  60  60 POINT (-75 38) POINT (75 36)
5  75  75 POINT (-82 35) POINT (82 38)

Me gustaría dibujar una línea entre pares de puntos dentro de df, así que desde un PUNTO en geometry hasta un PUNTO en geometry.1. He intentado lanzar los PUNTOS a un LINESTRING de la siguiente manera:

df %>% summarise(do_union=F) %>% st_cast("LINESTRING") %>% plot()

, pero esto no parece funcionar. Obtengo una línea continua, cuando lo que quiero son cinco líneas separadas.

r sf
6
Anthony W 29 sep. 2019 a las 00:03

1 respuesta

La mejor respuesta

Utilice mapply para crear una cadena de líneas uniendo los puntos por pares de las columnas de geometría:

> st_sfc(mapply(function(a,b){st_cast(st_union(a,b),"LINESTRING")}, df$geometry, df$geometry.1, SIMPLIFY=FALSE))
Geometry set for 5 features 
geometry type:  LINESTRING
dimension:      XY
bbox:           xmin: -85 ymin: 30 xmax: 85 ymax: 38
epsg (SRID):    NA
proj4string:    NA
LINESTRING (-85 34, 85 30)
LINESTRING (-80 36, 80 32)
LINESTRING (-78 37, 78 34)
LINESTRING (-75 38, 75 36)
LINESTRING (-82 35, 82 38)

Al principio pensé que st_union(geom1, geom2, by_feature=TRUE) sería suficiente para hacer la mayor parte del trabajo, pero (como se documenta) el by_feature se ignora con dos argumentos para st_union y la salida es una unión de cada uno de los 25 pares de funciones de geom1 y geom2.

Aquí hay una forma más lenta y torpe a través de una matriz de coordenadas:

> coords = cbind(st_coordinates(df$geometry), st_coordinates(df$geometry.1))

Construya cadenas de líneas por fila:

> linestrings = st_sfc(
     lapply(1:nrow(coords),
           function(i){
             st_linestring(matrix(coords[i,],ncol=2,byrow=TRUE))
           }))

Ver:

> plot(linestrings)

enter image description here

Si desea reemplazar la (primera) geometría del punto en su marco de datos con las líneas, entonces:

> st_geometry(df) = linestrings
6
Spacedman 29 sep. 2019 a las 21:00