Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Do I connect two coordinates with a line using Leaflet in R

I am trying to use Leaflet package in R to draw a amp and connect the markers given the latitude and longitude information in the table below.

      | Observation | InitialLat | InitialLong | NewLat    | NewLong   |     |-------------|------------|-------------|-----------|-----------|     | A           | 62.469722  | 6.187194    | 51.4749   | -0.221619 |     | B           | 48.0975    | 16.3108     | 51.4882   | -0.302621 |     | C           | 36.84      | -2.435278   | 50.861822 | -0.083278 |     | D           | 50.834194  | 4.298361    | 54.9756   | -1.62179  |     | E           | 50.834194  | 4.298361    | 54.9756   | -1.62179  |     | F           | 50.834194  | 4.298361    | 51.4882   | -0.302621 |     | G           | 47.460427  | -0.530804   | 51.44     | -2.62021  |     | H           | 51.5549    | -0.108436   | 53.4281   | -1.36172  |     | I           | 51.5549    | -0.108436   | 52.9399   | -1.13258  |     | J           | 51.5549    | -0.108436   | 51.889839 | -0.193608 |     |             | 51.5549    | -0.108436   | 52.0544   | 1.14554   |  

I want to draw lines from an initial point given by the coordinates in the InitialLat and InitialLong columns to an end point given by the NewLat and NewLong columns.

Here is my current R code which only draws the markers on the map.

      library(leaflet)     map3 = leaflet(data) %>% addTiles()     map3 %>% addMarkers(~InitialLong,~InitialLat, popup=~Observation)  
like image 762
maluwalmk Avatar asked Aug 28 '15 16:08

maluwalmk


People also ask

What does leaflet do in R?

leaflet is an open-source JavaScript library that is used to create dynamic online maps. The identically named R package makes it possible to create these kinds of maps in R as well.


2 Answers

Here is an alternative way using the leaflet package. I just took two data points in your data for the purpose of demonstration.

mydf <- data.frame(Observation = c("A", "B"),                    InitialLat = c(62.469722,48.0975),                    InitialLong = c(6.187194, 16.3108),                    NewLat = c(51.4749, 51.4882),                    NewLong = c(-0.221619, -0.302621),                    stringsAsFactors = FALSE) 

I changed the format of mydf and create a new data frame for leaflet. You can reshape your data in various ways.

mydf2 <- data.frame(group = c("A", "B"),                     lat = c(mydf$InitialLat, mydf$NewLat),                     long = c(mydf$InitialLong, mydf$NewLong))  #  group      lat      long #1     A 62.46972  6.187194 #2     B 48.09750 16.310800 #3     A 51.47490 -0.221619 #4     B 51.48820 -0.302621  library(leaflet) library(magrittr)  leaflet()%>% addTiles() %>% addPolylines(data = mydf2, lng = ~long, lat = ~lat, group = ~group) 

I trimmed the interactive map I got. Please see the map below. Although two lines are connected in this image, they are separated. If you run the code and zoom in, you will see that the two lines are separated.

enter image description here

like image 188
jazzurro Avatar answered Sep 24 '22 08:09

jazzurro


Leaflet can add lines using the addPolylines function. The problem with this is it assumes every line is connected - you will get them all linked.

The best way to fix this (AFAIK) is to use a loop:

library(leaflet) map3 = leaflet(data) %>% addTiles() map3 <- map3 %>% addMarkers(~InitialLong,~InitialLat, popup=~Observation) for(i in 1:nrow(data)){     map3 <- addPolylines(map3, lat = as.numeric(data[i, c(2, 4)]),                                 lng = as.numeric(data[i, c(3, 5)])) } map3 

EDIT: There is also an easier way using the points_to_line function by Kyle Walker (see the very bottom for a pasted copy of the code).

First reshape the data, so the starts and ends are in the same columns:

library(tidyr) library(dplyr) z <- gather(dta, measure, val, -Observation) %>% group_by(Observation) %>%             do(data.frame(   lat=c(.[["val"]][.[["measure"]]=="InitialLat"],                                    .[["val"]][.[["measure"]]=="NewLat"]),                           long = c(.[["val"]][.[["measure"]]=="InitialLong"],                                    .[["val"]][.[["measure"]]=="NewLong"]))) 

Then call points_to_line

z <- as.data.frame(z) y <- points_to_line(z, "long", "lat", "Observation") 

Now plot:

map3 = leaflet(data) %>% addTiles() map3 %>% addMarkers(~InitialLong, ~InitialLat, popup = ~Observation) %>%          addPolylines(data = y) 

Source of points_to_line by Kyle Walker:

library(sp) library(maptools)  points_to_line <- function(data, long, lat, id_field = NULL, sort_field = NULL) {    # Convert to SpatialPointsDataFrame   coordinates(data) <- c(long, lat)    # If there is a sort field...   if (!is.null(sort_field)) {     if (!is.null(id_field)) {       data <- data[order(data[[id_field]], data[[sort_field]]), ]     } else {       data <- data[order(data[[sort_field]]), ]     }   }    # If there is only one path...   if (is.null(id_field)) {      lines <- SpatialLines(list(Lines(list(Line(data)), "id")))      return(lines)      # Now, if we have multiple lines...   } else if (!is.null(id_field)) {        # Split into a list by ID field     paths <- sp::split(data, data[[id_field]])      sp_lines <- SpatialLines(list(Lines(list(Line(paths[[1]])), "line1")))      # I like for loops, what can I say...     for (p in 2:length(paths)) {       id <- paste0("line", as.character(p))       l <- SpatialLines(list(Lines(list(Line(paths[[p]])), id)))       sp_lines <- spRbind(sp_lines, l)     }      return(sp_lines)   } } 
like image 31
jeremycg Avatar answered Sep 24 '22 08:09

jeremycg