如何使用 Leaflet 在 R 中创建 GTFS 数据的交互式图?
How to create an interactive plot of GTFS data in R using Leaflet?
我想创建一个显示城市 public 交通线路的交互式地图。我正在尝试使用 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)
很高兴收到您的评论。
*我知道可以将此数据导入 GIS 软件(例如 QGIS)以创建 shapefile,然后使用 readOGR 将 shapefile 读入 R。 Robin Lovelace has shown how to do this。但是,我正在寻找纯 R 解决方案。 ;)
ps。 Kyle Walker has written a great intro to interactive maps in R using Leaflet。不幸的是,他没有在他的教程中介绍折线。
您的问题不是方法问题,而是数据问题:请注意,您下载了 8 MB,而您尝试通过 shiny 加载到 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
第 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"
是,类似,所以我们可以用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!
第 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)
}
第 4 阶段:情节
使用 SpatialLines
对象使代码更短一些 - 在这种情况下,这将绘制前 10 行:
leaflet() %>%
addTiles() %>%
addPolylines(data = shape_lines)
结论
在将数据转换为具有正确 ID 的 Spatial* 数据类型以进行绘图之前,您需要使用数据并对其进行操作。 maptools::map2Spatial*
、unique()
和一个聪明的 for
循环可以解决问题。
我想创建一个显示城市 public 交通线路的交互式地图。我正在尝试使用 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)
很高兴收到您的评论。
*我知道可以将此数据导入 GIS 软件(例如 QGIS)以创建 shapefile,然后使用 readOGR 将 shapefile 读入 R。 Robin Lovelace has shown how to do this。但是,我正在寻找纯 R 解决方案。 ;)
ps。 Kyle Walker has written a great intro to interactive maps in R using Leaflet。不幸的是,他没有在他的教程中介绍折线。
您的问题不是方法问题,而是数据问题:请注意,您下载了 8 MB,而您尝试通过 shiny 加载到 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
第 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"
是,类似,所以我们可以用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!
第 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)
}
第 4 阶段:情节
使用 SpatialLines
对象使代码更短一些 - 在这种情况下,这将绘制前 10 行:
leaflet() %>%
addTiles() %>%
addPolylines(data = shape_lines)
结论
在将数据转换为具有正确 ID 的 Spatial* 数据类型以进行绘图之前,您需要使用数据并对其进行操作。 maptools::map2Spatial*
、unique()
和一个聪明的 for
循环可以解决问题。