Wie kann man Linestrings effizient aus Punkten erstellen?

Dec 30 2020

Ich habe Geom-Punkte in zwei separaten Datenrahmen. Ich möchte Punkte mit einer Linie verbinden (später auf einer Karte). Deshalb möchte ich für jedes Punktpaar aus diesen Datenrahmen einen Linienstring erstellen. Ich habe es so gemacht:

coordsCust <- table %>%
  st_as_sf(coords = c("lonCust","latCust"), crs = 4326)

coordsApp <- table %>%
  st_as_sf(coords = c("lonApp","latApp"), crs = 4326) %>%
  st_geometry()

und Linestring:

lines <- st_sfc(mapply(function(a,b){
  st_cast(st_union(a,b),"LINESTRING")}, 
  coordsCust$geometry, coordsApp$geometry, SIMPLIFY=FALSE))

Dieser Code funktioniert, ich kann Zeile für Zeile Linestrings für jedes Punktepaar erstellen:

LINESTRING (14.035 51.65182, 14.33418 53.53346)
LINESTRING (20.42767 49.98073, 16.62978 52.31037)
LINESTRING (20.18762 50.03337, 16.62978 52.31037)
LINESTRING (19.04625 49.79234, 16.62978 52.31037)
LINESTRING (21.35808 50.92382, 16.62978 52.31037)

Das Problem ist, dass diese Lösung für 30 000 Zeilen sehr langsam arbeitet - ungefähr 21 Sekunden. Gibt es eine andere Möglichkeit, Linestrings aus Punkten zu erstellen? Etwas, das viel schneller funktioniert? Ich habe im Internet nach Lösungen gesucht, aber vergebens. Ich habe etwas über die Konvertierung von sf in Matrix und deren Verwendung gelesen, habe pmapaber keine Ahnung, wie ich es hier implementieren soll.

UPDATE: Wenn ich die Funktion sfheaders :: sf_linestring verwenden möchte, muss ich Geometrien aus beiden Datensätzen verbinden. So mach ich es:

df <- cbind(coordsCust,coordsApp)

und der endgültige Datenrahmen (ich habe den wichtigsten Teil davon gezeigt) ist unten gezeigt:

Leider funktioniert sf_linestring in diesem Datenrahmen nicht richtig. Ich muss Linestring zwischen POINTs für jede Zeile separat erstellen, wie auf dem Bildschirm gezeigt.

Antworten

2 SymbolixAU Dec 30 2020 at 04:49

Ohne einen Beispieldatensatz ist es schwierig, Ihre Frage vollständig zu beantworten. Wenn Sie Ihren data.frame jedoch in eine "lange" Form bringen können, sfheaderskönnen Sie dies sofort tun

n <- 30000
df <- data.frame(
  x = rnorm(n)
  , y = rnorm(n)
)

df$id <- rep(1:(n/2), each = 2)

sfheaders::sf_linestring(
  obj = df
  , x = "x"
  , y = "y"
  , linestring_id = "id"
)

# Simple feature collection with 15000 features and 1 field
# geometry type:  LINESTRING
# dimension:      XY
# bbox:           xmin: -4.297631 ymin: -4.118291 xmax: 3.782847 ymax: 4.053399
# CRS:            NA
# First 10 features:
#   id                       geometry
# 1   1 LINESTRING (0.2780517 0.243...
# 2   2 LINESTRING (0.4261505 2.503...
# 3   3 LINESTRING (0.8662821 -0.11...
# 4   4 LINESTRING (-0.5335952 -0.1...
# 5   5 LINESTRING (1.154309 -1.352...
# 6   6 LINESTRING (0.05512324 -0.4...
# 7   7 LINESTRING (1.945868 -0.744...
# 8   8 LINESTRING (0.0427066 -0.08...
# 9   9 LINESTRING (0.06738045 0.41...
# 10 10 LINESTRING (0.4128964 -0.04...