2

I have geom POINTs in two separate data frames. What I want to do is to connect points with a line (later on a map) so that's why I want to create Linestring for each pair of points from those data frames. I made it like this:

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

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

and Linestring:

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

This code works, I can create Linestrings for each pair of points, row by row:

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)

The issue is that for 30 000 rows this solution works really slow - about 21 seconds. Is there any other way to create linestrings from points? Something that works much faster? I searched for some solutions on the web but in vain. I've read something about converting sf to matrix and using pmap but have no idea how to implement it here.

UPDATE: if I want to use sfheaders::sf_linestring function I need to join geometries from both datasets. I do it like this:

df <- cbind(coordsCust,coordsApp)

and the final data frame (I showed most important part of it) is shown below:

enter image description here

Unfortunately sf_linestring doesn't work properly on this dataframe. I need to create linestring between POINTs for each row separately as shown on the screen.

mustafa00
  • 751
  • 1
  • 7
  • 28
  • 1
    Take a look at this other answer by @SymbolixAU : https://stackoverflow.com/a/51922422/7547327. It looks similar to your problem & you might be able to use it with `sfheaders` for its speed. – mrhellmann Dec 30 '20 at 12:34
  • Yes, I saw it either. The issue is that all those functions accept only numeric values, not geometry features. So I can't pass geom points to `st_linestring` or `sf_linestring`, only numeric values (e.g. coordinates of float type). Or maybe I'm wrong, I just noticed that. – mustafa00 Dec 30 '20 at 13:00

1 Answers1

3

Without an exmaple data set it's hard to completly answer your question. But if you can get your data.frame into 'long' form, then sfheaders can do this in an instant

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...
SymbolixAU
  • 25,502
  • 4
  • 67
  • 139
  • I have two seperate datasets with geom columns (POINTs) and in sfheaders case I see that I need to join them. I did it like this: `df <- cbind(coordsCust,coordsApp )`, then added id: `df$id <- seq(1:nrow(df))` and finally: `sfheaders::sf_linestring(obj = df, x = "geometry", y = "geometry.1", linestring_id = "id")`. Unfortunately I got error: `Not compatible with requested type: [type=list; target=double].` I also added some details to my main post above. – mustafa00 Dec 30 '20 at 09:32
  • seems I can't make it between geometry points, only between coordinates being floats/numeric – mustafa00 Dec 30 '20 at 11:29