2015-08-28 5 views
14

Sto provando ad usare il pacchetto Leaflet in R per disegnare un amplificatore e collegare i marker dati le informazioni di latitudine e longitudine nella tabella sottostante.Come collegare due coordinate con una linea utilizzando Leaflet in 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 | 

voglio tracciare linee da un punto iniziale dato dalle coordinate dei InitialLat e InitialLong colonne a un punto finale proposta dal NewLat e NewLong colonne.

Ecco il mio codice R attuale che disegna solo i marker sulla mappa.

 

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

risposta

15

Ecco un modo alternativo utilizzando il pacchetto leaflet. Ho appena preso due punti dati nei tuoi dati a scopo di dimostrazione.

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) 

ho cambiato il formato di mydf e creare un nuovo frame di dati per foglio. Puoi rimodellare i tuoi dati in vari modi.

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) 

Ho rifilato la mappa interattiva che ho ottenuto. Si prega di consultare la mappa qui sotto. Sebbene due linee siano collegate in questa immagine, sono separate. Se esegui il codice e ingrandisci, vedrai che le due linee sono separate.

enter image description here

9

Il volantino può aggiungere linee utilizzando la funzione addPolylines. Il problema con questo è che si presume che ogni linea sia connessa - li avrai tutti collegati.

Il modo migliore per risolvere questo problema (per quanto ne so) è quello di utilizzare un ciclo:

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: C'è anche un modo più semplice utilizzando il points_to_line function da Kyle Walker (vedi in fondo per una copia incollato di il codice).

Prima rimodellare i dati, in modo che le inizia e finisce sono nelle stesse colonne:

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"]))) 

quindi chiamare points_to_line

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

Ora trama:

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

Fonte di points_to_line di Kyle Walker:

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

So che questo è stato chiesto un anno fa, ma ho avuto la stessa domanda e capito come farlo in foglio.

Per prima cosa è necessario regolare il dataframe in quanto addPolyline collega semplicemente tutte le coordinate in una sequenza. Creerò un dataframe con 4 posizioni finali separate ai fini di questa dimostrazione.

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

Avanti, ho intenzione di creare una cornice di dati con la posizione centrale della stessa dimensione (4 in questo esempio) dei luoghi di destinazione.Spiegherò perché sto facendo questo presto

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

Il motivo per cui sto facendo questo è perché i addPolylines dispongono collegherà tutte le coordinate in una sequenza. Il modo per aggirare questo per creare l'immagine che hai descritto è iniziando dal punto di partenza, poi andando al punto di destinazione, e poi di nuovo al punto di partenza, e poi al prossimo punto di destinazione. Per creare il dataframe per fare questo, dovremo intrecciare le due dataframes mettendo in righe come tale:

punto di partenza - destinazione punto 1 - punto di partenza - punto di destinazione 2 - e così via ...

Il modo in cui lo farò è creare una chiave per entrambi i frame di dati. Per il dataframe di origine, inizierò da 1 e incrementerò di 2 (ad es. 1 3 5 7). Per il dataframe di destinazione, inizierò da 2 e incrementerò di 2 (ad es. 2, 4, 6, 8). Quindi combinerò i 2 dataframes usando un UNION all. Quindi selezionerò la sequenza per fare di ogni altra riga il punto di partenza. Userò sqldf per questo perché è quello con cui mi trovo a mio agio. Potrebbe esserci un modo più efficiente.

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) 

Il nuovo dataframe assomiglia a questo Notice how the origin locations are interwoven between the destination

E, infine, è possibile rendere la vostra mappa:

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

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

And finally it should look like this Spero che questo aiuta qualcuno che sta cercando di fare qualcosa di simile in futuro

1

A seconda dello scopo delle linee, un altro ottima opzione è gcIntermediate(). Emette un oggetto SpatialLines CURVED, basato sulla curvatura della terra. Non eccezionale per le indicazioni però. Gli oggetti di classe SpatialLines funzionano molto bene con Leaflet. Vedi here per un esempio eccellente. Ho pubblicato un modulo modificato, che inizia con la cornice dati di 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()