2015-08-28 2 views
14

Я пытаюсь использовать пакет Leaflet в R, чтобы нарисовать усилитель и подключить маркеры, учитывая информацию о широте и долготе в таблице ниже.Как связать две координаты с линией, используя Лист в R

 

    | Observation | InitialLat | InitialLong | NewLat | NewLong | 
    |-------------|------------|-------------|-----------|-----------| 
    | A   | 62.469722 | 6.187194 | 51.4749 | -0.221619 | 
    | B   | 48.0975 | 16.3108  | 51.4882 | -0.302621 | 
    | C   | 36.84  | -2.435278 | 50.861822 | -0.083278 | 
    | D   | 50.834194 | 4.298361 | 54.9756 | -1.62179 | 
    | E   | 50.834194 | 4.298361 | 54.9756 | -1.62179 | 
    | F   | 50.834194 | 4.298361 | 51.4882 | -0.302621 | 
    | G   | 47.460427 | -0.530804 | 51.44  | -2.62021 | 
    | H   | 51.5549 | -0.108436 | 53.4281 | -1.36172 | 
    | I   | 51.5549 | -0.108436 | 52.9399 | -1.13258 | 
    | J   | 51.5549 | -0.108436 | 51.889839 | -0.193608 | 
    |    | 51.5549 | -0.108436 | 52.0544 | 1.14554 | 

Я хочу, чтобы рисовать линии от начальной точки, заданной координатами в InitialLat и InitialLong колонн к конечной точке, заданной в NewLat и NewLong колонн.

Вот мой текущий код R, который только рисует маркеры на карте.

 

    library(leaflet) 
    map3 = leaflet(data) %>% addTiles() 
    map3 %>% addMarkers(~InitialLong,~InitialLat, popup=~Observation) 

ответ

15

Вот альтернативный способ использования пакета leaflet. Я просто взял два данных в ваших данных для демонстрации.

mydf <- data.frame(Observation = c("A", "B"), 
        InitialLat = c(62.469722,48.0975), 
        InitialLong = c(6.187194, 16.3108), 
        NewLat = c(51.4749, 51.4882), 
        NewLong = c(-0.221619, -0.302621), 
        stringsAsFactors = FALSE) 

Я изменил формат mydf и создать новый фрейм данных для буклета. Вы можете изменить свои данные различными способами.

mydf2 <- data.frame(group = c("A", "B"), 
        lat = c(mydf$InitialLat, mydf$NewLat), 
        long = c(mydf$InitialLong, mydf$NewLong)) 

# group  lat  long 
#1  A 62.46972 6.187194 
#2  B 48.09750 16.310800 
#3  A 51.47490 -0.221619 
#4  B 51.48820 -0.302621 

library(leaflet) 
library(magrittr) 

leaflet()%>% 
addTiles() %>% 
addPolylines(data = mydf2, lng = ~long, lat = ~lat, group = ~group) 

Я урезал интерактивную карту, которую я получил. См. Карту ниже. Хотя на этом изображении две линии связаны, они разделены. Если вы запустите код и увеличите масштаб, вы увидите, что две линии разделены.

enter image description here

9

Листовка может добавлять линии, используя функцию addPolylines. Проблема с этим заключается в том, что предполагается, что каждая строка подключена - вы получите их все связанные.

Лучший способ исправить это (AFAIK) является использование цикла:

library(leaflet) 
map3 = leaflet(data) %>% addTiles() 
map3 <- map3 %>% addMarkers(~InitialLong,~InitialLat, popup=~Observation) 
for(i in 1:nrow(data)){ 
    map3 <- addPolylines(map3, lat = as.numeric(data[i, c(2, 4)]), 
           lng = as.numeric(data[i, c(3, 5)])) 
} 
map3 

EDIT: Существует также более простой способ использования points_to_line function Кайл Уокер (см самое дно для вставленного копии код).

Сначала перекроить данные, так что начинается и заканчивается в тех же столбцах:

library(tidyr) 
library(dplyr) 
z <- gather(dta, measure, val, -Observation) %>% group_by(Observation) %>% 
      do(data.frame( lat=c(.[["val"]][.[["measure"]]=="InitialLat"], 
            .[["val"]][.[["measure"]]=="NewLat"]), 
          long = c(.[["val"]][.[["measure"]]=="InitialLong"], 
            .[["val"]][.[["measure"]]=="NewLong"]))) 

Затем вызовите points_to_line

z <- as.data.frame(z) 
y <- points_to_line(z, "long", "lat", "Observation") 

Теперь сюжет:

map3 = leaflet(data) %>% addTiles() 
map3 %>% addMarkers(~InitialLong, ~InitialLat, popup = ~Observation) %>% 
     addPolylines(data = y) 

Источник points_to_line Кайл Уокер:

library(sp) 
library(maptools) 

points_to_line <- function(data, long, lat, id_field = NULL, sort_field = NULL) { 

    # Convert to SpatialPointsDataFrame 
    coordinates(data) <- c(long, lat) 

    # If there is a sort field... 
    if (!is.null(sort_field)) { 
    if (!is.null(id_field)) { 
     data <- data[order(data[[id_field]], data[[sort_field]]), ] 
    } else { 
     data <- data[order(data[[sort_field]]), ] 
    } 
    } 

    # If there is only one path... 
    if (is.null(id_field)) { 

    lines <- SpatialLines(list(Lines(list(Line(data)), "id"))) 

    return(lines) 

    # Now, if we have multiple lines... 
    } else if (!is.null(id_field)) { 

    # Split into a list by ID field 
    paths <- sp::split(data, data[[id_field]]) 

    sp_lines <- SpatialLines(list(Lines(list(Line(paths[[1]])), "line1"))) 

    # I like for loops, what can I say... 
    for (p in 2:length(paths)) { 
     id <- paste0("line", as.character(p)) 
     l <- SpatialLines(list(Lines(list(Line(paths[[p]])), id))) 
     sp_lines <- spRbind(sp_lines, l) 
    } 

    return(sp_lines) 
    } 
} 
0

Я знаю, что это был задан вопрос год назад, но у меня был тот же вопрос и понял, как сделать это в листовке.

Прежде всего, вам нужно настроить свой фреймворк, потому что addPolyline просто соединяет все координаты в последовательности. Для этой демонстрации я создам DataFrame с 4 отдельными конечными местоположениями.

dest_df <- data.frame (lat = c(41.82, 46.88, 41.48, 39.14), 
        lon = c(-88.32, -124.10, -88.33, -114.90) 
       ) 

Далее я собираюсь создать фрейм данных с центральным расположением одного и того же размера (4 в этом примере) в местах назначения.Я объясню, почему я делаю это скоро

orig_df <- data.frame (lat = c(rep.int(40.75, nrow(dest_df))), 
        long = c(rep.int(-73.99,nrow(dest_df))) 
       ) 

Причина, почему я делаю это потому, что addPolylines особенность соединит все координаты в последовательности. Чтобы обойти это, чтобы создать изображение, которое вы описали, начинайте с начальной точки, затем переходите к точке назначения, а затем обратно в начальную точку, а затем в следующую точку назначения. Для того, чтобы создать dataframe, чтобы сделать это, мы должны будем сплетаются два dataframes путем размещения в строках, как например:

отправной точка - пункт назначения 1 - начальная точка - пункт назначения 2 - и так далее ...

То, как я буду делать, это создать ключ для обоих кадров данных. Для исходного кадра данных я начну с 1 и увеличу на 2 (например, 1 3 5 7). Для целевого блока данных я начну с 2 и увеличится на 2 (например, 2, 4, 6, 8). Затем я объединю 2 кадра данных с помощью UNION all. Затем я буду сортировать по моей последовательности, чтобы сделать каждую другую строку отправной точкой. Я собираюсь использовать sqldf для этого, потому что мне это нравится. Возможно, более эффективный способ.

orig_df$sequence <- c(sequence = seq(1, length.out = nrow(orig_df), by=2)) 
dest_df$sequence <- c(sequence = seq(2, length.out = nrow(orig_df), by=2)) 

library("sqldf") 
q <- " 
SELECT * FROM orig_df 
UNION ALL 
SELECT * FROM dest_df 
ORDER BY sequence 
" 
poly_df <- sqldf(q) 

Новый dataframe выглядит следующим образом Notice how the origin locations are interwoven between the destination

И, наконец, вы можете сделать свою карту:

library("leaflet") 
leaflet() %>% 
    addTiles() %>% 

    addPolylines(
    data = poly_df, 
    lng = ~lon, 
    lat = ~lat, 
    weight = 3, 
    opacity = 3 
) 

And finally it should look like this Я надеюсь, что это помогает любому, кто ищет, чтобы сделать что-то вроде этого в будущем

1

В зависимости от цели линии, другой Большой вариант - gcIntermediate(). Он выводит объект CURVED SpatialLines, основанный на кривизне земли. Не очень хорошо для направлений. Объекты класса SpatialLines очень хорошо работают с Leaflet. См. here для превосходного примера. Я опубликовал модифицированную форму, которая начинается с фрейма данных от Paul Reiners.

library(leaflet) 
library(geosphere) 

mydf <- data.frame(InitialLat = c(62.469722,48.0975), # initial df 
       InitialLong = c(6.187194, 16.3108), 
       NewLat = c(51.4749, 51.4882), 
       NewLong = c(-0.221619, -0.302621)) 

p1 <- as.matrix(mydf[,c(2,1)]) # it's important to list lng before lat here 
p2 <- as.matrix(mydf[,c(4,3)]) # and here 

gcIntermediate(p1, p2, 
      n=100, 
      addStartEnd=TRUE, 
      sp=TRUE) %>% 
leaflet() %>% 
addTiles() %>% 
addPolylines() 
Смежные вопросы