web-dev-qa-db-fra.com

Comment connecter deux coordonnées avec une ligne en utilisant Leaflet in R

J'essaie d'utiliser le paquet Leaflet dans R pour dessiner un ampli et connecter les marqueurs en fonction des informations de latitude et de longitude indiquées dans le tableau ci-dessous.


 | Observation | InitialLat | InitialLong | NewLat | NewLong | 
 | ------------- | ------------ | ------------- | -------- --- | ----------- | 
 | Un | 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 | 
 | Je | 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 | 

Je veux tracer des lignes d'un point initial donné par les coordonnées des colonnes InitialLat et InitialLong à un point final donné par les colonnes NewLat et NewLong.

Voici mon code R actuel qui ne dessine que les marqueurs sur la carte.


 bibliothèque (dépliant) 
 map3 = notice (données)%>% addTiles () 
 map3%>% addMarkers (~ InitialLong, ~ InitialLat, popup = ~ Observation) 

17
maluwalmk

Voici une autre solution utilisant le package leaflet. Je viens de prendre deux points de données dans vos données à des fins de démonstration.

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)

J'ai changé le format de mydf et créer un nouveau bloc de données pour le dépliant. Vous pouvez remodeler vos données de différentes manières. 

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)

J'ai découpé la carte interactive que j'ai obtenue. S'il vous plaît voir la carte ci-dessous. Bien que deux lignes soient connectées dans cette image, elles sont séparées. Si vous exécutez le code et effectuez un zoom avant, vous verrez que les deux lignes sont séparées.

 enter image description here

17
jazzurro

Leaflet peut ajouter des lignes à l’aide de la fonction addPolylines. Le problème, c'est que chaque ligne est connectée - vous les aurez toutes liées.

Le meilleur moyen de résoudre ce problème (autant que je sache) consiste à utiliser une boucle:

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: Il existe également un moyen plus simple d’utiliser la fonction points_to_line de Kyle Walker (voir tout en bas pour une copie collée du code).

Tout d'abord remodeler les données, les débuts et les fins sont dans les mêmes colonnes:

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

Ensuite, appelez points_to_line

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

Maintenant parcelle:

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

Source de points_to_line par 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)
  }
}
9
jeremycg

Selon l'objectif des lignes, gcIntermediate () est une autre excellente option. Il génère un objet CURVED SpatialLines, basé sur la courbure de la terre. Pas génial pour les directions cependant. Les objets de classe SpatialLines fonctionnent très bien avec Leaflet. Voir ici pour un excellent exemple. J'ai posté un formulaire modifié, qui commence par le bloc de données de 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()
2
Susan

Pense que celui-ci est ce que tu veux:

install.packages("leaflet")
library(leaflet)

mydf <- data.frame(Observation = c("A", "B","C","D","E"),
               InitialLat = c(62.469722,48.0975,36.84,50.834194,50.834194),
               InitialLong = c(6.187194, 16.3108,-2.435278,4.298361,4.298361),
               NewLat = c(51.4749, 51.4882,50.861822,54.9756,54.9756),
               NewLong = c(-0.221619, -0.302621,-0.083278,-1.62179,-1.62179),
               stringsAsFactors = FALSE)

mydf
 Observation InitialLat InitialLong   NewLat   NewLong
1           A   62.46972    6.187194 51.47490 -0.221619
2           B   48.09750   16.310800 51.48820 -0.302621
3           C   36.84000   -2.435278 50.86182 -0.083278
4           D   50.83419    4.298361 54.97560 -1.621790
5           E   50.83419    4.298361 54.97560 -1.621790

m<-leaflet(data=mydf)%>%addTiles
for (i in 1:nrow(mydf)) 
m<-m%>%addPolylines(lat=c(mydf[i,]$InitialLat,mydf[i,]$NewLat),lng=c(mydf[i,]$InitialLong,mydf[i,]$NewLong))

Et cela montre: Connexion réseau avec Leaflet

1
Lili Duan

Je sais que cela a été demandé il y a un an, mais j'avais la même question et j'ai trouvé comment le faire dans un dépliant.

Vous allez d'abord devoir ajuster votre cadre de données, car addPolyline ne fait que connecter toutes les coordonnées dans une séquence. Je vais créer un cadre de données avec 4 emplacements finaux distincts aux fins de cette démonstration. 

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

Ensuite, je vais créer un bloc de données avec l'emplacement central de la même taille (4 dans cet exemple) des emplacements de destination. Je vais expliquer pourquoi je le fais bientôt

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

La raison pour laquelle je le fais est que la fonctionnalité addPolylines connectera toutes les coordonnées dans une séquence. Pour contourner ce problème afin de créer l'image que vous avez décrite, vous devez commencer par le point de départ, puis aller au point de destination, puis revenir au point de départ, puis au point de destination suivant. Pour créer le cadre de données à cette fin, nous devrons entrelacer les deux cadres de données en les plaçant comme tels:

point de départ - point de destination 1 - point de départ - point de destination 2 - et ainsi de suite ...

Je vais créer une clé pour les deux blocs de données. Pour la trame de données Origin, je commencerai à 1 et j'incrémenterai de 2 (par exemple, 1 3 5 7). Pour le cadre de données de destination, je commencerai par 2 et incrémenterai de 2 (par exemple, 2, 4, 6, 8). Je combinerai ensuite les 2 images en utilisant un UNION all. Je vais ensuite trier selon ma séquence pour faire de chaque rangée le point de départ. Je vais utiliser sqldf pour cela car c'est ce avec quoi je suis à l'aise. Il peut y avoir un moyen plus efficace.

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)

La nouvelle structure de données se présente comme suit Notez comment les emplacements d'origine sont entrelacés entre la destination

Et enfin, vous pouvez faire votre carte:

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

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

Et finalement, cela devrait ressembler à ceci J'espère que cela aidera tous ceux qui cherchent à faire quelque chose comme ça à l'avenir

1
David Sung