web-dev-qa-db-ja.com

Rのリーフレットを使用して2つの座標を線で接続するにはどうすればよいですか

Rでリーフレットパッケージを使用してアンプを描画し、下の表にある緯度と経度の情報を基にマーカーを接続しようとしています。

 
 |観察| 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 | 
 |私| 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 = 〜観察)
 
20
maluwalmk

leafletパッケージを使用する別の方法を次に示します。デモンストレーションの目的で、データから2つのデータポイントを取得しました。

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)

取得したインタラクティブマップをトリミングしました。下の地図をご覧ください。この画像では2本の線が接続されていますが、分離しています。コードを実行してズームインすると、2つの行が分離されていることがわかります。

enter image description here

19
jazzurro

リーフレットは、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

編集: 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)
  }
}
12
jeremycg

行の目的に応じて、gcIntermediate()を使用することもできます。地球の曲率に基づいて、CURVED SpatialLinesオブジェクトを出力します。道順はあまりよくありません。 SpatialLinesクラスオブジェクトは、Leafletで非常にうまく機能します。優れた例については こちら を参照してください。 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

これはあなたが望むものだと思います:

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

そしてそれは示しています: リーフレットを使用したネットワーク接続

2
Lili Duan

私はこれが1年前に尋ねられたことを知っていますが、同じ質問があり、リーフレットでそれを行う方法を理解しました。

AddPolylineはシーケンス内のすべての座標を接続するだけなので、最初にデータフレームを調整する必要があります。このデモの目的で、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機能がシーケンス内のすべての座標を接続するためです。説明した画像を作成するためにこれを回避する方法は、開始点から開始して、目的点に移動し、次に開始点に戻り、次に次の目的点に戻ることです。これを行うデータフレームを作成するには、次のように行に配置して2つのデータフレームをインターレースする必要があります。

始点-終点1-始点-終点2など.

私が行う方法は、両方のデータフレームのキーを作成することです。 Originデータフレームでは、1から開始し、2ずつインクリメントします(例:1 3 5 7)。宛先データフレームについては、2から開始し、2ずつ増分します(2、4、6、8など)。次に、UNION allを使用して2つのデータフレームを結合します。次に、シーケンスで並べ替えて、1行おきの行を開始点にします。私はこれに慣れているので、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)

新しいデータフレームは次のようになります Originの場所が宛先間でどのように織り交ぜられているかに注意してください

そして最後に、あなたはあなたの地図を作ることができます:

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

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

そして最終的には次のようになるはずです これが将来このようなことをしたいと考えている人を助けることを願っています

2
David Sung