Miguel Rivera Rios Miguel Rivera Rios - 25 days ago 18
R Question

Mapping Bus Routes with Leaflet in R

I recently found this shape file of NYC bus routes shape file of NYC bus routes (zip file) that I am interested in plotting with the leaflet package in R.

When I attempt to do so, some routes do not show up on the map. I can tell they're missing because I overlay the bus stop data and some do not line up with the routes.

When I read in the shape file, I notice that the spatial lines data frame that is created has nested lists, which I think leaflet is not mapping.

What do I need to do so that leaflet reads coordinates of these missing routes? Below is the code I used to produce the map with missing routes:

bus <- readOGR(dsn = path.expand("bus_route_shapefile"), layer = "bus_route_shapefile")
bus.pj <- spTransform(bus, CRS("+proj=longlat +datum=WGS84"))
bus.st <- readOGR(dsn = path.expand("bus_stop_shapefile"), layer = "bus_stop_shapefile")
bus.st.pj <- spTransform(bus.st, CRS("+proj=longlat +datum=WGS84"))

bus_map <- leaflet() %>%
setView(lng = -73.932667, lat = 40.717266, zoom = 11) %>%
addPolylines(data = bus.pj, color = "black", opacity = 1) %>%
addCircles(data=bus.st.pj@data,~stop_lon, ~stop_lat, color = "red") %>%
addTiles()
bus_map

Answer

It would be easier to help you if you provided not only bus_routes but also bus_stop (zip file). You can solve it by converting bus.pj into new SpatialLinesxxx obj where each class Lines has only one class Line. SLDF below code makes doesn't have bus.pj@data$trip_heads because of unknown.

library(dplyr); library(sp); library(leaflet)

  ## resolve bus.pj@lines into list(Line.objs)   (Don't worry about warnings)
Line_list <- lapply(bus.pj@lines, getLinesLinesSlot) %>% unlist()

       ## If you want just Lines infromation, finish with this line.
     SL <- sapply(1:length(Line_list), function(x) Lines(Line_list[[x]], ID = x)) %>% 
       SpatialLines()

  ## make new ids (originalID_nth)
ori_id <- getSLLinesIDSlots(bus.pj)                         # get original ids
LinLS <- sapply(bus.pj@lines, function(x) length(x@Lines))  # how many Line.obj does each Lines.obj has
new_id <- sapply(1:length(LinLS), function(x) paste0(x, "_", seq.int(LinLS[[x]]))) %>% 
  unlist()

  ## make a new data.frame (only route_id)
df <- data.frame(route_id = rep(bus.pj@data$route_id, times = LinLS))
rownames(df) <- new_id

  ## integrate Line.objs, ids and a data.frame into SpatialLinesDataFrame.obj
SLDF <- mapply(function(x, y) Lines(x, ID = y), x = Line_list, y = new_id) %>% 
  SpatialLines() %>% SpatialLinesDataFrame(data = df)


leaflet() %>%
  setView(lng = -73.932667, lat = 40.717266, zoom = 11) %>%
  addPolylines(data = SLDF, color = "black", opacity = 1, weight = 1) %>% 
  addCircles(data=bus.st.pj@data,~stop_lon, ~stop_lat, color = "red", weight = 0.3)

enter image description here

Comments