流程图(旅行路径)在R中使用Lat和Long

时间:2017-05-31 11:38:55

标签: r ggplot2 leaflet gis r-leaflet

我正在尝试绘制流程图(适用于新加坡)。我有Entry(Lat,Long)和Exit(Lat,long)。我试图在新加坡地图中绘制从入口到出口的流量。

protected override ICommonComponentVM CreateInstance(IContext context)
{
    var param = context.Parameters.Single((arg) => arg.Name == "type");
    if (param == null){
        return null;
    }
    var type = (CommonVMTypes)param.GetValue(context, null); //<-- Needs an Action ITarget

    switch (type)
    // ...
}

我想尝试一下这个:Map Flow

5 个答案:

答案 0 :(得分:7)

刚才意识到使用geom_path的原始解决方案比必要的更复杂。 geom_segment无需更改数据即可运行:

require(ggplot2)
require(ggmap)
basemap <- get_map("Singapore",
                   source = "stamen",
                   maptype = "toner",
                   zoom = 11)

g = ggplot(a)
map = ggmap(basemap, base_layer = g)
map = map + coord_cartesian() +
      geom_curve(size = 1.3,
                 aes(x=as.numeric(Entry_Station_Long),
                     y=as.numeric(Entry_Station_Lat),
                     xend=as.numeric(as.character(Exit_Station_Long)),
                     yend=as.numeric(as.character(Exit_Station_Lat)),
                     color=as.factor(token_id)))
map

此解决方案利用Draw curved lines in ggmap, geom_curve not working在地图上实现曲线。

ggmaps用于简单 - 对于更具野心的项目,我建议leaflet

enter image description here

使用长数据格式和一些先前的数据争论解决方案。它也使用直线而不是上面的曲线。

a %>%
  mutate(path = row_number()) -> a

origin = select(a,token_id,Entry_Station_Lat,Entry_Station_Long,path)
origin$type = "origin"
dest = select(a,token_id,Exit_Station_Lat,Exit_Station_Long,path)
dest$type = "dest"

colnames(origin) = c("id","lat","long","path","type")
colnames(dest) = c("id","lat","long","path","type")
complete = rbind(origin,dest)
complete %>% arrange(path,type) -> complete

require(ggmap)
basemap <- get_map("Singapore",
                   source = "stamen",
                   maptype = "toner",
                   zoom = 11)

g = ggplot(complete, aes(x=as.numeric(long),
                         y=as.numeric(lat)))
map = ggmap(basemap, base_layer = g)

map + geom_path(aes(color = as.factor(id)),
                size = 1.1)

enter image description here

答案 1 :(得分:4)

如果您想在实际的Google地图上绘制它,并重新创建链接地图的样式,您可以使用我的googleway包使用Google的Maps API。您需要API密钥才能使用他们的地图

library(googleway)

df$Exit_Station_Lat <- as.numeric(as.character(df$Exit_Station_Lat))
df$Exit_Station_Long <- as.numeric(as.character(df$Exit_Station_Long))

df$polyline <- apply(df, 1, function(x) {
    lat <- c(x['Entry_Station_Lat'], x['Exit_Station_Lat'])
    lon <- c(x['Entry_Station_Long'], x['Exit_Station_Long'])
    encode_pl(lat = lat, lon = lon)
})

mapKey <- 'your_api_key'

style <- '[ { "stylers": [{ "visibility": "simplified"}]},{"stylers": [{"color": "#131314"}]},{"featureType": "water","stylers": [{"color": "#131313"},{"lightness": 7}]},{"elementType": "labels.text.fill","stylers": [{"visibility": "on"},{"lightness": 25}]}]'

google_map(key = mapKey, style = style) %>%
    add_polylines(data = df, 
      polyline = "polyline", 
      mouse_over_group = "Entry_Station_Lat",
      stroke_weight = 0.7,  
      stroke_opacity = 0.5, 
      stroke_colour = "#ccffff")

enter image description here

注意,要使用航班数据重新创建地图,请参阅?add_polylines

中给出的示例

您还可以显示其他类型的路线,例如,使用Google的Directions API对这些路线进行驾驶来对行车路线进行编码。

df$drivingRoute <- lst_directions <- apply(df, 1, function(x){
    orig <- as.numeric(c(x['Entry_Station_Lat'], x['Entry_Station_Long']))
    dest <- as.numeric(c(x['Exit_Station_Lat'], x['Exit_Station_Long']))

    dir <- google_directions(origin = orig, destination = dest, key = apiKey)
    dir$routes$overview_polyline$points
})


google_map(key = mapKey, style = style) %>%
    add_polylines(data = df, 
      polyline = "drivingRoute", 
      mouse_over_group = "Entry_Station_Lat",
      stroke_weight = 0.7,  
      stroke_opacity = 0.5, 
      stroke_colour = "#ccffff")

enter image description here

答案 2 :(得分:4)

使用leafletgeosphere

的替代答案
#get Packages
require(leaflet)
require(geosphere)

#format data
a$Entry_Station_Long = as.numeric(as.character(a$Entry_Station_Long))
a$Entry_Station_Lat = as.numeric(as.character(a$Entry_Station_Lat))
a$Exit_Station_Long = as.numeric(as.character(a$Exit_Station_Long))
a$Exit_Station_Lat = as.numeric(as.character(a$Exit_Station_Lat))
a$id = as.factor(as.numeric(as.factor(a$token_id)))

#create some colors
factpal <- colorFactor(heat.colors(30), pathList$id)

#create a list of interpolated paths
pathList = NULL
for(i in 1:nrow(a))
{
tmp = gcIntermediate(c(a$Entry_Station_Long[i],
                 a$Entry_Station_Lat[i]),
               c(a$Exit_Station_Long[i],
                 a$Exit_Station_Lat[i]),n = 25,
               addStartEnd=TRUE)
tmp = data.frame(tmp)
tmp$id = a[i,]$id
tmp$color = factpal(a[i,]$id)
pathList = c(pathList,list(tmp))
}

#create empty base leaflet object
leaflet() %>% addTiles() -> lf

#add each entry of pathlist to the leaflet object
for (path in pathList)
{
  lf %>% addPolylines(data = path,
                      lng = ~lon, 
                      lat = ~lat,
                      color = ~color) -> lf

}
#show output
lf

请注意,正如我之前提到的那样,没有办法在如此小的地方划分路径 - 大圆是有效的直线。如果你想要圆润的边缘为了美观,你可能必须使用我的另一个答案中描述的geom_curve方式。

enter image description here

答案 3 :(得分:2)

我还编写了mapdeck库,以使这种可视化效果更具吸引力*

library(mapdeck)

set_token("MAPBOX_TOKEN")  ## set your mapbox token here

df$Exit_Station_Lat <- as.numeric(as.character(df$Exit_Station_Lat))
df$Exit_Station_Long <- as.numeric(as.character(df$Exit_Station_Long))

mapdeck(
  style = mapdeck_style('dark')
  , location = c(104, 1)
  , zoom = 8
  , pitch = 45
) %>%
  add_arc(
    data = df
    , origin = c("Entry_Station_Long", "Entry_Station_Lat")
    , destination = c("Exit_Station_Long", "Exit_Station_Lat")
    , layer_id = 'arcs'
    , stroke_from_opacity = 100
    , stroke_to_opacity = 100
    , stroke_width = 3
    , stroke_from = "#ccffff"
    , stroke_to = "#ccffff"
  )

enter image description here

*主观地说

答案 4 :(得分:1)

我想为您留下另一种方法。您可以做的是重组您的数据。现在,您有两列用于入口站,另外两列用于出站。您可以通过组合这些列来创建一个长列,另一个用于lat。诀窍是使用rbind()c()

让我们来看看这个简单的例子。

x <- c(1, 3, 5)
y <- c(2, 4, 6)
c(rbind(x, y))

#[1] 1 2 3 4 5 6

想象一下,x对于入口站来说是长的,对于出口站来说是y。 1是经度的起点。 2是第一次旅程结束的经度。从我的示例数据中可以看出,3似乎是相同的2.您可以删除每个token_id的重复数据点。如果您有大量数据,也许这是您想要考虑的事情。回到主要点,您可以使用两个函数的组合以所需的顺序创建具有经度的列。由于您说您有日期信息,请确保按日期订购数据。然后,每个旅程的顺序以tmp的正确方式显示。你也想用纬度来做这件事。

现在我们查看您的示例数据。 Exit_Station_LatExit_Station_Long似乎是因素。第一个操作是将它们转换为数字。然后,应用上述方法并创建数据框。我调用了您的数据mydf

library(dplyr)
library(ggplot2)
library(ggalt)
library(ggthemes)
library(raster)

mydf %>%
mutate_at(vars(Exit_Station_Lat: Exit_Station_Long),
          funs(as.numeric(as.character(.)))) -> mydf

group_by(mydf, token_id) %>%
do(data.frame(long = c(rbind(.$Entry_Station_Long,.$Exit_Station_Long)),
              lat = c(rbind(.$Entry_Station_Lat, .$Exit_Station_Lat))
             )
   ) -> tmp

现在让我们从GADM获取地图数据。您可以使用raster包下载数据。

getData(name = "GADM", country = "singapore", level = 0) %>%
fortify -> singapore

最后,你绘制一张地图。关键是在group的{​​{1}}中使用aes。我希望这会让你前进。

geom_path()

enter image description here