Search code examples
spatialr-sfr-sp

Connect two sets of sfc points with arrows


I have a dataframe two columns of which are lists of sfc points.

 > head(moves)
   hiring                      start                        end
 1      1 POINT (-2.030474 51.36306) POINT (-2.250102 51.41609)
 2      2 POINT (-2.319776 51.46162) POINT (-2.491189 51.41029)
 3      4 POINT (-2.025846 51.47712) POINT (-2.063781 51.49158)
 4      6 POINT (-2.426711 51.38076) POINT (-2.132722 51.46999)
 5      7  POINT (-2.116654 51.4887) POINT (-2.204403 51.51874)
 6      8  POINT (-2.122917 51.5861) POINT (-2.134635 51.51806)

I need to draw lines (ideally, pointed) from one point to another, row by row. My problem seems to be that my file(moves) is not an sf object. Do I need to make it one, or take the data from it into some other format?

 > dput(head(moves))
 structure(list(hiring = c(1L, 2L, 4L, 6L, 7L, 8L), start = list(
     structure(c(-2.03047447566941, 51.3630641761757), class = c("XY", 
     "POINT", "sfg")), structure(c(-2.31977575385362, 51.4616210429381
     ), class = c("XY", "POINT", "sfg")), structure(c(-2.02584648038463, 
     51.4771163047678), class = c("XY", "POINT", "sfg")), 
 structure(c(-2.42671091326068, 
     51.3807643595824), class = c("XY", "POINT", "sfg")), 
 structure(c(-2.1166538974769, 
     51.4887039877758), class = c("XY", "POINT", "sfg")), 
 structure(c(-2.12291705783767, 
     51.5860957106472), class = c("XY", "POINT", "sfg"))), end = list(
     structure(c(-2.25010169528537, 51.4160891285008), class = c("XY", 
    "POINT", "sfg")), structure(c(-2.49118920138511, 51.4102939905029
     ), class = c("XY", "POINT", "sfg")), structure(c(-2.06378098244424, 
     51.491583244303), class = c("XY", "POINT", "sfg")), 
 structure(c(-2.13272163343155, 
     51.469987047928), class = c("XY", "POINT", "sfg")), 
 structure(c(-2.20440279315621, 
     51.5187438721622), class = c("XY", "POINT", "sfg")), 
 structure(c(-2.1346350057738, 
     51.5180564842074), class = c("XY", "POINT", "sfg")))), row.names = c(NA, 
 6L), class = "data.frame")

Solution

  • Simple arrows with base graphics on a empty background (no map).

    EDIT: With the data now given in the original post I realize that moves$start and moves$end aren't sfc objects but simply lists of sfg objects. They can be turned into sfc objects with sf::st_as_sfc and then the coordinates can be extracted. Full code is:

    library(sf)
    #> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1
    moves <- structure(
      list(hiring = c(1L, 2L, 4L, 6L, 7L, 8L), 
           start = list(
             structure(c(-2.03047447566941, 51.3630641761757),
                       class = c("XY", "POINT", "sfg")), 
             structure(c(-2.31977575385362, 51.4616210429381), 
                       class = c("XY", "POINT", "sfg")), 
             structure(c(-2.02584648038463, 51.4771163047678), 
                       class = c("XY", "POINT", "sfg")), 
             structure(c(-2.42671091326068, 51.3807643595824), 
                       class = c("XY", "POINT", "sfg")), 
             structure(c(-2.1166538974769, 51.4887039877758), 
                       class = c("XY", "POINT", "sfg")), 
             structure(c(-2.12291705783767, 51.5860957106472), 
                       class = c("XY", "POINT", "sfg"))),
           end = list(
             structure(c(-2.25010169528537, 51.4160891285008), 
                       class = c("XY", "POINT", "sfg")), 
             structure(c(-2.49118920138511, 51.4102939905029), 
                       class = c("XY", "POINT", "sfg")), 
             structure(c(-2.06378098244424, 51.491583244303), 
                       class = c("XY", "POINT", "sfg")), 
             structure(c(-2.13272163343155, 51.469987047928), 
                       class = c("XY", "POINT", "sfg")), 
             structure(c(-2.20440279315621, 51.5187438721622), 
                       class = c("XY", "POINT", "sfg")), 
             structure(c(-2.1346350057738, 51.5180564842074), 
                       class = c("XY", "POINT", "sfg")))), 
           w.names = c(NA, 6L), class = "data.frame")
    
    co_s <- st_coordinates(st_as_sfc(moves$start))
    co_e <- st_coordinates(st_as_sfc(moves$end))
    s_lon <- co_s[,"X"]
    s_lat <- co_s[,"Y"]
    e_lon <- co_e[,"X"]
    e_lat <- co_e[,"Y"]
    plot(c(s_lon, e_lon), c(s_lat, e_lat), col = rep(c("red", "blue"), each = 6),
         pch = 20, cex = 2, xlab = "lon", ylab = "lat")
    arrows(s_lon, s_lat, e_lon, e_lat)