美文网首页
R_leaflet包_最易上手地图教程(一)(下)

R_leaflet包_最易上手地图教程(一)(下)

作者: 天善智能 | 来源:发表于2019-03-07 10:20 被阅读2次

    欢迎关注天善智能,我们是专注于商业智能BI,人工智能AI,大数据分析与挖掘领域的垂直社区,学习,问答、求职一站式搞定!

    对商业智能BI、大数据分析挖掘、机器学习,python,R等数据领域感兴趣的同学加微信:tstoutiao,邀请你进入数据爱好者交流群,数据爱好者们都在这儿。

    作者:李誉辉

    四川大学在读研究生

    最近一直在寻找方便上手的地图包,实验了google地图包,百度地图包,发现还是有很多限制。

    百度地图包搭配的REmap总是崩溃,

    google地图包ggmap现在需要国际信用卡注册,总之,都不甚满意。

    虽然ggplot2地图功能非常丰富,但是还是不够简单快捷。

    尤其是当我们仅仅需要绘制一些简单的地图时。

    经过圈子大佬的推荐,开始尝试leaflet包,确实给我很多惊喜。

    leaflet包相对其它地图包,有很多优点和缺点,

    首先,绘制地图简单快捷,因为都是基于供应商的tiles,一行代码就可以render出基本widget地图。

    支持管道传参,一个图层一个图层进行添加,代码结构更加清晰。

    其次,有很多tiles供应商可以选择,包括高德、google、Stamen, Esri, OpenWeatherMap,NASA,

    等好几十个tiles供应商。当然其中一些需要注册。其中的google可以绕过注册,已经很难得了。

    对于在地图上添加markers图标,shapes形状,线条等,异常方便快捷,这在ggplot2中很难做到的。

    支持栅格数据,rasters栅格数据是基于像素点的地图。可以看出,leaflet具有很强的包容性。

    支持多种投影坐标系,甚至可以自定义坐标系,这在某些特殊场景非常重要。

    当然还有更重要的是,其具有一定交互能力,可以缩放拖拽,

    简单的图层切换也不需要使用Shiny。使得更容易上手。

    其它特点,首先tiles是基于供应商的,必须联网,

    其次对颜色支持不一样,只支持HEX颜色空间和colors()中的颜色名称。 当然内置的几个palette函数,非常特别。

    总之,笔者认为leaflet包与ggplot2包的互补性非常好,刚好弥补了ggplot2中画地图的不足。

    对于大量数据需要呈现在地图上的场景,还是`ggplot2, leaflet中插入其它plots不便也没有必要。

    下面是笔者总结的中文教程,使得新人能更快上手。

    说明:以下图片皆为截图,限于技术问题,不能完全展现它的交互式功能。

    5.形状与线条

    在leaflet中,添加形状和线条非常容易。

    多边形和折线

    线条和多边形数据源可以从以下途径获取:

    SpatialPolygons(), SpatialPolygonsDataFrame(),

    Polygons()和Polygon()对象(来自sp包)

    SpatialLines(), SpatialLinesDataFrame(), Lines(), 和Line()对象(来自sp包)

    MULTIPOLYGON(), POLYGON(), MULTILINESTRING()和LINESTRING()对象(来自sp包)

    map()对象(来自maps包)。

    使用map(fill = TRUE)得到多边形数据,使用map(fill = FALSE)得到折线段数据

    2列的矩阵,第1列为经度,第2列为纬度。多边形之间用(NA, NA)行分开。

    但是对于多边形内部存在空洞,这种方法失效,须使用SpatialPolygons()。

    5.1

    circles形状

    使用addCircles()添加circle形状。

    绘制circle形状时,仅仅需要圆心坐标和半径。使用radius参数指定半径。

    1library(leaflet)

    2

    3cities <- read.csv(textConnection("

    4City,Lat,Long,Pop

    5Boston,42.3601,-71.0589,645966

    6Hartford,41.7627,-72.6743,125017

    7New York City,40.7127,-74.0059,8406000

    8Philadelphia,39.9500,-75.1667,1553000

    9Pittsburgh,40.4397,-79.9764,305841

    10Providence,41.8236,-71.4222,177994

    11"))

    12

    13leaflet(cities) %>% addTiles() %>% addCircles(lng = ~Long, lat = ~Lat, weight = 1,

    14 radius = ~sqrt(Pop) * 30, popup = ~City, fillColor = "magenta", fillOpacity = 0.2)

    5.2

    Rectangles矩形

    一个矩形仅仅需要2组经纬度数据(对应矩形2个对角点),

    分别为lng1, lng2, lat1, lat2共4个数字向量

    矩形坐标数据不能像其它多边形一样从sp,maps包或2列矩阵,或2列数据框中得到。

    因为其它多边形数据都是1组点的坐标数据(分组连线成多边形),而矩形数据是2组点的坐标数据。

    使用addRectangles()函数添加矩形图层。

    1library(leaflet)

    2

    3leaflet() %>% addTiles() %>% addRectangles(lng1 = -118.456554, lat1 = 34.078039,

    4 lng2 = -118.436383, lat2 = 34.062717, fillColor = "transparent" # fillColor = 'transparent'与fillColor = NULL结果不一样

    5)

    5.3

    addPolygons()

    语法:

    1addPolygons(map, lng = NULL, lat = NULL, layerId = NULL,

    2 group = NULL, stroke = TRUE, color = "#03F", weight = 5,

    3 opacity = 0.5, fill = TRUE, fillColor = color, fillOpacity = 0.2,

    4 dashArray = NULL, smoothFactor = 1, noClip = FALSE, popup = NULL,

    5 popupOptions = NULL, label = NULL, labelOptions = NULL,

    6 options = pathOptions(), highlightOptions = NULL,

    7 data = getMapData(map))

    参数解释:

    stroke, 表示是否显示多边形的路径阴影。

    color, 表示指定stroke的颜色。

    weight, 表示指定stroke像素宽度。

    smoothFactor, 表示指定多边形的polyLines(边线)简化因子。越大,则边缘约平滑。

    opacity, 表示指定stroke透明度,opacity从0(完全透明)到1(完全不透明)

    fillOpacity, 表示指定多边形fill透明度,opacity从0(完全透明)到1(完全不透明)

    fillColor, 表示指定多边形fill填充颜色,

    highlightOptions, 表示高亮鼠标所在区域的多边形。

    指定高亮参数用highlightOptions()函数。

    5.3.1 highlightOptions()高亮多边形

    高亮多边形,就是改变鼠标所在区域多边形的颜色和透明度等参数。

    语法:

    1highlightOptions(stroke = NULL, color = NULL, weight = NULL,

    2 opacity = NULL, fill = NULL, fillColor = NULL,

    3 fillOpacity = NULL, dashArray = NULL, bringToFront = NULL,

    4 sendToBack = NULL)

    参数解释:

    dashArray, 表示指定多边形stroke的线型,与Popup中用法一致。

    bringToFront, 表示当鼠标悬浮在所在多边形区域时,

    是否将该shape置于表层。这对于高亮shape是必须的。

    sendToBack, 表示当鼠标移走时,是否将高亮shape置于底层。

    下图为美国人口数据图,数据来源(https://www.census.gov/geo/maps-data/data/cbf/cbf_state.html)需要科学上网。

    1library(leaflet)

    2

    3path <- "E:/R_input_output/data_input/cb_2013_us_state_20m/cb_2013_us_state_20m.shp"

    4states <- rgdal::readOGR(path,layer = "cb_2013_us_state_20m",

    5 GDAL1_integer64_policy = TRUE)# 读取数据

    6

    7neStates <- subset(states, states$STUSPS %in% c(

    8 "CT","ME","MA","NH","RI","VT","NY","NJ","PA"

    9))

    10

    11leaflet(neStates) %>%

    12 addPolygons(color = "cyan", weight = 1, smoothFactor = 0.5,

    13 opacity = 1.0, fillOpacity = 0.5,

    14 fillColor = ~colorQuantile("YlOrRd", ALAND)(ALAND),

    15 highlightOptions = highlightOptions(color = "white", weight = 2, # 高亮形状区域,置于表层。

    16 bringToFront = TRUE))

    1## OGR data source with driver: ESRI Shapefile

    2## Source: "E:R_input_outputdata_inputcb_2013_us_state_20mcb_2013_us_state_20m.shp", layer: "cb_2013_us_state_20m"

    3## with 52 features

    4## It has 9 fields

    5## Integer64 fields read as doubles: ALAND AWATER

    5.3.2 简化polygons/polylines

    对于形状复杂的地图多边形和折线,直接使用leaflet绘图容易出现一些问题,

    并且运算量大, 因为数据点太多了。

    很多时候,对数据进行简化是必要的,

    简化后的图形与没有简化的在普通分辨率下根本分辨不出来差别。

    使用rmapshaper::ms_simplify()简化很方便,

    其基于拓扑学原理进行简化,数据存储量小,形状失真小。

    albersusa包安装方式:devtools::install_github("hrbrmstr/albersusa")

    1library(albersusa)

    2

    3fullsize <- usa_sf() # albersusa包自带数据

    4object.size(fullsize) # object.size属于utils包,R自带

    5

    6simplified <- rmapshaper::ms_simplify(fullsize)

    7object.size(simplified) # 可以看出,这种简化方式存储量只有原来1/8

    1## 933016 bytes

    2## 123920 bytes

    6.GeoJSON与TopoJSON数据

    对于GeoJSON和TopoJSON类型数据,有2种处理方式:

    要么读取为sp对象;要么使用addGeoJSON()和addTopoJSON()函数。

    6.1

    直接读取GeoJSON/TopoJSON

    GeoJSON格式与TopoJSON格式是不一样的。

    **GeoJSON格式文件后缀是”.geojson“

    TopoJSONg格式文件后缀是”.json“**。

    地图数据集都可以在线转换,推荐使用GiS Map Converter

    支持多种格式免费转换,邮箱注册非常方便。

    也可以使用MyGeodata Converter(https://mygeodata.cloud/converter/)

    使用addGeoJSON()或addTopoJSON()函数可以直接读取JSON文件,

    但是很多参数不能修改,还是转换成sp对象最好。

    6.1.1 addGeoJSON()

    下面用到的地图数据来自于中国省级地图下载(https://pan.baidu.com/share/init?surl=f5344XfW7X1wqXuTsNONSw)0,密码:vhk6

    直接给geojson参数指定文件路径。

    注意:使用本地JSON文件或leafletCN绘图,在markdown中码代码,不能直接knitr到html.

    Script中码代码可以输出为本地html文件。但是只能在一个html中输出一张图。

    所以笔者接下来的图形均使用截图。

    1library(leaflet)

    2

    3filepath <- "E:/R_input_output/data_input/China.geojson"

    4

    5leaflet() %>%

    6 setView(lng = 106.33, lat = 29.35, zoom = 3.5) %>% # 以重庆城区经纬度为中心

    7 addTiles() %>%

    8 addGeoJSON(geojson = filepath,

    9 weight = 1, color = "magenta", fill = FALSE) # 修改color失败

    6.1.2 addTopoJSON()

    直接给topojson参数指定文件路径。

    1library(leaflet)

    2

    3filepath <- "E:/R_input_output/data_input/JSON/TopoJson/China.json"

    4

    5leaflet() %>%

    6 setView(lng = 106.33, lat = 29.35, zoom = 3.5) %>% # 以重庆城区经纬度为中心

    7 addTiles() %>%

    8 addTopoJSON(topojson = filepath, weight = 1,

    9 color = "magenta", fill = FALSE) # 修改color失败

    6.2

    sp对象

    使用geojsonio或rgdal包,读取GeoJSON/TopoJSON对象为sp对象。

    然后就能使用sp对象作图。

    此方法设置或修改地图区域的特征属性方面更加方便,如colors, labels等。

    对于GeoJSON文件,可以用记事本打开看一下数据结构,然后再读取。

    也可以用JSON在线解析器(http://geojson.io/#map=2/20.0/0.0)查看,更加方便。

    读取GeoJSON还是TopoJson格式,函数的使用方法是一样的。

    1library(leaflet)

    2library(rgdal)

    3

    4filepath <- "E:/R_input_output/data_input/JSON/TopoJson/China.json"

    5# filepath <- "E:/R_input_output/data_input/JSON/GeoJSON/China.geojson" # 结果一样

    6China_map <- readOGR(filepath, stringsAsFactors = FALSE)

    7# China_map <- geojsonio::geojson_read(filepath,what = "sp") # 结果一样

    8

    9Encoding(China_map@data$name) <- "UTF-8" # 纠正中文字符乱码

    10leaflet(China_map) %>%

    11 setView(lng = 106.33, lat = 29.35, zoom = 3.5) %>% # 以重庆城区经纬度为中心

    12 addPolygons(stroke = TRUE, color = "magenta", smoothFactor = 0.3,

    13 fillOpacity = 0.5,fillColor = "lime") %>%

    14 addMarkers(lng = 114.3,lat = 30.6 ) # 增加一个图标

    (图片太大,没截全)

    6.3

    修改style(样式)

    对于GeoJSON/TopoJSO格式数据中的特征属性来说,

    有2种方法进行修改(目前仅仅修改paths和shapes, 不支持markers):

    其一是在addGeoJSON()和addTopoJSON()函数中设置参数。

    另一种方法是对JSON对象(字符串),重新编码styling信息,

    通过直接在JSON数据的top level的JSON 对象下面直接插入1个style对象。

    下一个代码块是关于设置全局styles和在JSON数据中插入style对象的例子。

    在R中不推荐使用这种方法设置styles, 通常还是首先将数据转换成sp对象,再进行绘图更加方便。

    但是,如果你掌控了GeoJSON/TopoJSON数据的生成过程,直接插入style对象是可取的。

    1library(leaflet)

    2library(jsonlite)

    3

    4filepath <- "E:/R_input_output/data_input/JSON/TopoJson/China.json"

    5# filepath <- "E:/R_input_output/data_input/JSON/GeoJSON/China.geojson" # 结果一样

    6

    7# 首先解析JSON格式为stringified格式,再转化为多级列表

    8China_map_list <- readLines(filepath, warn = FALSE) %>%

    9 paste(collapse = "") %>%

    10 fromJSON(simplifyVector = FALSE) # 将JSON格式转化为多级列表

    11

    12# 插入style对象,增加子列表

    13China_map_list$style <- list(

    14 weight = 1,

    15 stroke = "TRUE",

    16 color = "magenta",

    17 fillColor = "lime",

    18 opacity = 0.5,

    19 fillOpacity = 0.8

    20)

    21

    22

    23# 使用修改了style的JSON数据绘图

    24leaflet() %>% setView(lng = 106.33, lat = 29.35, zoom = 3.5) %>% # 以重庆城区经纬度为中心

    25 addTopoJSON(China_map_list) %>%

    26 # addGeoJSON(China_map_list) %>% # 若读取China.geojson文件,

    27 addMarkers(lng = 114.3,lat = 30.6 ) # 增加一个图标

    (图片太大,没截全)

    往期精彩:

    不用代码,从搜索数据中解读星巴克“猫爪杯”如何挠你的心

    是否,是否,总是富肥穷瘦?(文末上周投票公布)

    R语言自然语言处理:词性标注与命名实体识别

    R语言中文社区2018年终文章整理(作者篇)

    R语言中文社区2018年终文章整理(类型篇)

    相关文章

      网友评论

          本文标题:R_leaflet包_最易上手地图教程(一)(下)

          本文链接:https://www.haomeiwen.com/subject/bgiqpqtx.html