简体   繁体   中英

leaflet add multiple polylines

I have seen similar questions but so far none that fit my needs (at least to the extent I understand them) so I will apologize in advance if this has already been answered. I am also kind of an R novice.

I have a data frame containing two sets of Lat/Lon in each row. The actual data contains hundreds of rows and many columns of related data. I am plotting the points for both sets of Lat/Lon and want to draw lines connecting each pair as a separate line. Here is an example of what the results should look like.

[![enter image description here][1]][1]

Here is a simplified example of the data. There will be duplicate Event and Location values.

Event_lat   Event_lon   Event   Location    Location_latitude   Location_longitude
40.791151   -124.054008 704832643   60005   40.790961   -124.1825609
38.900882   -122.660353 704653051   60009   38.873889   -122.709722
38.921488   -122.600049 704681147   60011   38.85111099 -122.593333
38.921488   -122.600049 704681147   60011   38.85111099 -122.593333
39.141877   -123.044724 706777142   60012   39.22794396 -123.064722
38.928113   -122.611386 708644013   60016   38.98950003 -122.7695828
39.02361    -122.72195  708582623   60016   38.98950003 -122.7695828
38.87586    -122.842684 708336092   60016   38.98950003 -122.7695828
39.239926   -123.145497 709020144   60017   39.24138798 -123.2163878
39.3307 -123.221674 708875205   60017   39.24138798 -123.2163878

Here is a simplified sample of the code to map the points:

library(leaflet)
myData <-read.csv("Book1.csv",header=TRUE, sep=",")
leaflet()%>%
  addTiles() %>%
  addCircles(myData,lng = myData$lsr_lon,lat = myData$lsr_lat, radius=20, color = "red",group = "events") %>% 
  addCircles(myData,lng = myData$site_longitude,lat = myData$site_latitude, radius=20, color = "blue",group = 'Locations')

I myself am just starting with geographic use of R and leaflet, so this probably is not the most efficient way to approach this problem.. Nevertheless it is working fine for me... Feedback is always welcome!

result

结果

sample data

df <- read.table( text = "Event_lat   Event_lon   Event   Location    Location_latitude   Location_longitude
40.791151   -124.054008 704832643   60005   40.790961   -124.1825609
38.900882   -122.660353 704653051   60009   38.873889   -122.709722
38.921488   -122.600049 704681147   60011   38.85111099 -122.593333
38.921488   -122.600049 704681147   60011   38.85111099 -122.593333
39.141877   -123.044724 706777142   60012   39.22794396 -123.064722
38.928113   -122.611386 708644013   60016   38.98950003 -122.7695828
39.02361    -122.72195  708582623   60016   38.98950003 -122.7695828
38.87586    -122.842684 708336092   60016   38.98950003 -122.7695828
39.239926   -123.145497 709020144   60017   39.24138798 -123.2163878
39.3307 -123.221674 708875205   60017   39.24138798 -123.2163878", header = TRUE)

code

I want to create a spatiallines-object, that I can draw in leaflet with addPolylines .

First, i want to create a data.frame with lat/lon only, with a unique id per combination of event-location.

library(tidyverse)
#craete a column with unique id's per event-location combination
df <- df %>% mutate( id = row_number() )
#create a temporaty df with events
events.df <- df %>% 
  select( id, Event_lat, Event_lon) %>% 
  rename( latitude = Event_lat, longitude = Event_lon)
#create a temporaty df with locations
locations.df <- df %>% 
  select( id, Location_latitude, Location_longitude) %>%
  rename( latitude = Location_latitude, longitude = Location_longitude)
#merge the two temp.df's together
df.sp <- bind_rows( events.df, locations.df )

#    id latitude longitude
# 1   1 40.79115 -124.0540
# 2   2 38.90088 -122.6604
# 3   3 38.92149 -122.6000
# 4   4 38.92149 -122.6000
# 5   5 39.14188 -123.0447
# 6   6 38.92811 -122.6114
# 7   7 39.02361 -122.7220
# 8   8 38.87586 -122.8427
# 9   9 39.23993 -123.1455
# 10 10 39.33070 -123.2217
# 11  1 40.79096 -124.1826
# 12  2 38.87389 -122.7097
# 13  3 38.85111 -122.5933
# 14  4 38.85111 -122.5933
# 15  5 39.22794 -123.0647
# 16  6 38.98950 -122.7696
# 17  7 38.98950 -122.7696
# 18  8 38.98950 -122.7696
# 19  9 39.24139 -123.2164
# 20 10 39.24139 -123.2164

Now to create the spatialLines-object

library(maptools)
library(sp)
#make df.sp a spatialdataframe
coordinates( df.sp ) <- c( "longitude", "latitude" )

#create a list per id
id.list <- sp::split( df.sp, df.sp[["id"]] )

#initialisation of counter
id <- 1

#for each id, create a line that connects all points with that id
for ( i in id.list ) {
  event.lines <- SpatialLines( list( Lines( Line( i[1]@coords ), ID = id ) ),
                               proj4string = CRS( "+init=epsg:4326" ) )
  if ( id == 1 ) {
    sp_lines  <- event.lines
  } else {
    sp_lines  <- spRbind( sp_lines, event.lines )
  }
  id <- id + 1
}

check.

head(sp_lines,1)

# An object of class "SpatialLines"
# Slot "lines":
#   [[1]]
# An object of class "Lines"
# Slot "Lines":
#   [[1]]
# An object of class "Line"
# Slot "coords":
#   longitude latitude
# [1,] -124.0540 40.79115
# [2,] -124.1826 40.79096
# 
# Slot "ID":
#   [1] "1"
# 
# Slot "bbox":
#   min        max
# x -124.18256 -124.05401
# y   40.79096   40.79115
# 
# Slot "proj4string":
#   CRS arguments:
#   +init=epsg:4326 +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0 

Now, draw the points and the polylines in leaflet

library(leaflet)
leaflet()%>%
  addTiles() %>%
  addCircles(df,lng = df$Event_lon, lat = df$Event_lat, radius=20, color = "red", group = "events") %>% 
  addCircles(df,lng = df$Location_longitude, lat = df$Location_latitude, radius=20, color = "blue", group = 'Locations') %>%
  addPolylines( data = sp_lines )

I propose a solution using library(sf) and library(data.table) , where sf has superseeded sp , and data.table is used for efficient reshaping of data.

I am using the data provided by Wimpel in their solution.

Reshaping

Creating an sf object is fairly straight forward. We need to create a LINESTRING for each row of your data (as an sfg object), then convert to sf

library(sf)
library(data.table)

setDT(df)   

## create an 'id' / index value. This assumes each row of your data is a separate line. 
df[, idx := .I]

## create an `sfc` column (where each row is an `sfg` object)
sf <- df[
    , {
        geometry <- sf::st_linestring(x = matrix(c(Event_lon, Event_lat, Location_longitude, Location_latitude), ncol = 2, byrow = T))
        geometry <- sf::st_sfc(geometry)
        geometry <- sf::st_sf(geometry = geometry)
    }
    , by = idx
]

## convert to sf
sf <- sf::st_as_sf(sf)

Plotting

With this sf object you can now plot in leaflet (using similar code to Wimpel)

library(leaflet)

leaflet() %>%
    addTiles() %>%
    addPolylines(data = sf) %>%
    addCircles(data = df, lng = ~Event_lon, lat = ~Event_lat, radius=20, color = "red", group = "events") %>% 
    addCircles(data = df, lng = ~Location_longitude, lat = ~Location_latitude, radius=20, color = "blue", group = 'Locations') 

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM