如何使用Leaflet在R中创建GTFS数据的交互式图?

raf*_*ira 8 gis dictionary r gtfs leaflet

我想创建一个显示城市公共交通线路的互动地图.我正在尝试使用R中的Leaflet(但我对替代方案,建议是开放的吗?)

数据:传输系统的数据采用GTFS格式,以文本文件(.txt)组织,我将其作为数据框读入R.

问题:我找不到如何指示每条Poly线的id(变量shape_id),因此该图实际上将遵循每条传输线的路线.相反,它是以随机顺序连接点.

这是我尝试过的,到目前为止没有成功:

# Download GTFS data of the Victoria Regional Transit System
  tf <- tempfile() 
  td <- tempdir()
  ftp.path <- "http://www.gtfs-data-exchange.com/agency/bc-transit-victoria-regional-transit-system/latest.zip"
  download.file(ftp.path, tf) 

# Read text file to a data frame
  zipfile <- unzip( tf , exdir = td )
  shape <- read.csv(zipfile[9])

# Create base map
  basemap <- leaflet() %>% addTiles()


# Add transit layer
  basemap  %>% addPolylines(lng=shape$shape_pt_lon, lat=shape$shape_pt_lat, 
                            fill = FALSE,
                            layerId =shape$shape_id) 
Run Code Online (Sandbox Code Playgroud)

我很乐意对此发表意见.

*我知道可以将这些数据导入GIS软件(例如QGIS)以创建shapefile,然后使用readOGR将shapefile读入R. Robin Lovelace已经展示了如何做到这一点.但是,我正在寻找纯R解决方案.;)

PS.Kyle Walker使用Leaflet为R中的交互式地图写了一篇很棒的介绍.不幸的是,他没有在他的教程中介绍多边形线.

Rob*_*ace 11

您的问题不是方法而是数据:注意您下载8 MB并且您尝试通过闪亮加载到Leaflet的行文件是5 MB.作为一般原则,在扩展之前,您应该首先尝试使用微小数据集的新方法.这就是我在下面做的,以诊断问题并解决它.

第1阶段:探索和分组数据

pkgs <- c("leaflet", "shiny" # packages we'll use
  , "maps" # to test antiquated 'maps' data type
  , "maptools" # to convert 'maps' data type to Spatial* data
  )
lapply(pkgs, "library", character.only = TRUE)


class(shape)
## [1] "data.frame"

head(shape)

##   shape_id shape_pt_lon shape_pt_lat shape_pt_sequence
## 1 1-39-220    -123.4194     48.49065                 0
## 2 1-39-220    -123.4195     48.49083                 1
## 3 1-39-220    -123.4195     48.49088                 2
## 4 1-39-220    -123.4196     48.49123                 3
## 5 1-39-220    -123.4197     48.49160                 4
## 6 1-39-220    -123.4196     48.49209                 5

object.size(shape) / 1000000 # 5 MB!!!

## 5.538232 bytes

summary(shape$shape_id)
shape$shape_id <- as.character(shape$shape_id)
ids <- unique(shape$shape_id)
shape_orig <- shape
shape <- shape[shape$shape_id == ids[1],] # subset the data
Run Code Online (Sandbox Code Playgroud)

第2阶段:转换为Spatial*对象

这就像data.frame地图中的对象吗?

state.map <- map("state", plot = FALSE, fill = TRUE)
str(state.map)

## List of 4
##  $ x    : num [1:15599] -87.5 -87.5 -87.5 -87.5 -87.6 ...
##  $ y    : num [1:15599] 30.4 30.4 30.4 30.3 30.3 ...
##  $ range: num [1:4] -124.7 -67 25.1 49.4
##  $ names: chr [1:63] "alabama" "arizona" "arkansas" "california" ...
##  - attr(*, "class")= chr "map"
Run Code Online (Sandbox Code Playgroud)

是的,它是相似的,所以我们可以map2Spatial*用来转换它:

shape_map <- list(x = shape$shape_pt_lon, y = shape$shape_pt_lat)
shape_lines <- map2SpatialLines(shape_map, IDs = ids[1])
plot(shape_lines) # success - this plots a single line!
Run Code Online (Sandbox Code Playgroud)

线

第3阶段:将所有线路连接在一起

一个for循环可以做得很好.注意我们只使用前10行.使用2:length(ids)的所有行:

for(i in 2:10){
  shape <- shape_orig[shape_orig$shape_id == ids[i],]
  shape_map <- list(x = shape$shape_pt_lon, y = shape$shape_pt_lat)
  shape_temp <- map2SpatialLines(shape_map, IDs = ids[i])
  shape_lines <- spRbind(shape_lines, shape_temp)
}
Run Code Online (Sandbox Code Playgroud)

第四阶段:情节

使用该SpatialLines对象使代码更短 - 在这种情况下,这将绘制前10行:

leaflet() %>% 
  addTiles() %>%
  addPolylines(data = shape_lines)
Run Code Online (Sandbox Code Playgroud)

第一-10

结论

在将数据转换为用于绘图的Spatial*数据类型之前,您需要使用数据并对其进行操作,并使用正确的ID.maptools::map2Spatial*,unique()一个聪明的for循环可以解决问题.