2015-02-26 5 views
8

Я хотел бы создать интерактивную карту, показывающую общественные транспортные маршруты города. Я пытаюсь сделать это с помощью Leaflet в R (но я открыт для альтернатив, предложений?)Как создать интерактивный график данных GTFS в R, используя Листовку?

Данные: данные транспортной системы в формате GTFS, организованные в текстовые файлы (.txt), которые я читать в R в качестве кадра данных. *

Проблема: я не могу найти, как указать идентификатор каждой строки Poly (переменная 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) 

Я был бы рад, чтобы ваши комментарии по этому поводу.

* Я знаю, что можно импортировать эти данные в программное обеспечение ГИС (например, QGIS) для создания шейп-файла, а затем прочитать шейп-файл в R с помощью readOGR. Robin Lovelace has shown how to do this. НО, я ищу чистое решение R. ;)

пс. Kyle Walker has written a great intro to interactive maps in R using Leaflet. К сожалению, он не покрывает полилинии в своем учебнике.

ответ

9

Ваша проблема заключается не в методе, а в данных: обратите внимание, что вы загружаете 8 МБ и что файл линии, который вы пытаетесь загрузить в Листовку через блестящий, составляет 5 МБ. Как общий принцип, вы всегда должны сначала попробовать новые методы с крошечными наборами данных, прежде чем масштабировать их. Это то, что я делаю ниже, чтобы диагностировать проблему и решить ее.

Этап 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! 

line

Этап 3: Join все линии вместе

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: Участок

Использование объекта делает код немного короче - это будет строить первые 10 строк в этом случае:

leaflet() %>% 
    addTiles() %>% 
    addPolylines(data = shape_lines) 

first-10

Заключение

Вам нужно было поиграть с данными и манипулировать ими, прежде чем преобразовывать их в тип данных Spatial * для построения с правильными идентификаторами. maptools::map2Spatial*, unique() и умный for цикл может решить проблему.

+0

Он отлично работает Робин. Спасибо. Я думал о «проблеме данных», о которой вы говорили. Потому что, в конце концов, когда я применяю ваше решение для сопоставления всех транзитных маршрутов, ваш код также загружает в Листовку объект размером 5 МБ (shape_lines). –

+0

Правда, что, но для целей тестирования и воспроизводимости проблемы следует уменьшить до наименьшей/простейшей формы – RobinLovelace

Смежные вопросы