tmap_arrange对象传入tmap_leaflet报错及图注不显示问题咨询
问题背景
在交互式R Markdown报告中使用tmap制作地图时,为实现图题、图号的自动调用与交叉引用,需要将tmap生成的地图转换为leaflet对象。单张地图的转换可正常运行,参考代码如下:
library(tmap) tmap_mode("view") data(World) w1 <- World[1,] w1_map <- tm_shape(w1) + tm_polygons() tmap_leaflet(w1_map)
将经tmap_arrange()并排排列的两张地图传入tmap_leaflet()函数时会触发报错,但单独调用tmap_arrange()生成的并排地图可正常展示,复现代码如下:
library(tmap) data(World) w1 <- World[1,] w2 <- World[2,] tmap_mode("view") w1_map <- tm_shape(w1) + tm_polygons() w2_map <- tm_shape(w2) + tm_polygons() two_maps <- tmap_arrange(w1_map, w2_map) two_maps # 单独调用可正常显示 tmap_leaflet(two_maps) # 传入转换函数触发报错
触发的报错信息为:
Error in if (!is.na(g$style)) { : argument is of length zero
补充测试情况
参考建议使用htmltools::tagList()排布转换后的leaflet地图时,代码块设置的图注无法正常显示,测试代码如下:
```{r side-by-side, echo = TRUE, eval = TRUE, message = FALSE, warning = FALSE, fig.cap = "Some maps"} library(tmap) library(htmltools) data(World) w1 <- World[1,] w2 <- World[2,] tmap_mode("view") w1_map <- tm_shape(w1) + tm_polygons() w2_map <- tm_shape(w2) + tm_polygons() w1_map_lf <- tmap_leaflet(w1_map) w2_map_lf <- tmap_leaflet(w2_map) leaflet_grid <- tagList( tags$figure( tags$table(width = "100%", tags$tr( tags$td(w1_map_lf), tags$td(w2_map_lf) ) ) ) ) leaflet_grid ```
问题原因
该问题不属于个人操作失误,是tmap的原生功能限制:
tmap_leaflet()的设计定位是单张视图模式tmap对象到leaflet对象的转换函数,内部仅实现了单图对象的解析逻辑,没有适配tmap_arrange()生成的多图组合类对象,传入后会因内部读取不到对应绘图参数触发你遇到的报错。- 直接调用
tmap_arrange()可以正常显示并排交互图,是因为tmap针对视图模式下的多图排版单独写了htmlwidget渲染逻辑,没有走tmap_leaflet()的单图转换路径。 - 手动用
tagList()拼接leaflet对象无法显示图注,是因为手动拼接的原生HTML标签集合不属于knitr可识别的标准绘图输出对象,代码块上配置的fig.cap参数不会自动绑定到这类手动生成的HTML内容上,因此图注不会被渲染。
解决方案
不需要手动将tmap对象转为leaflet再拼接,直接使用视图模式下tmap_arrange()的原生输出即可满足需求:tmap_arrange()在view模式下返回的本身就是合法的htmlwidget交互对象,会被knitr正常识别为绘图输出,直接在代码块上配置fig.cap参数即可自动生成图题、图号,支持R Markdown/bookdown的交叉引用功能,参考代码如下:
```{r side-by-side, echo = TRUE, eval = TRUE, message = FALSE, warning = FALSE, fig.cap = "并排展示的两张交互式世界地图"} library(tmap) tmap_mode("view") data(World) w1 <- World[1,] w2 <- World[2,] w1_map <- tm_shape(w1) + tm_polygons() w2_map <- tm_shape(w2) + tm_polygons() # 直接输出多图排版结果即可,无需手动调用tmap_leaflet tmap_arrange(w1_map, w2_map, ncol = 2) ```
如果确实需要对单张地图做leaflet层面的自定义修改(比如添加专属控件、绑定自定义交互事件),可以先分别将单张tmap转为leaflet对象完成定制,再使用leaflet.extras2::addLeafletsync()实现多图并排与联动,最后通过htmlwidgets::onRender绑定图注即可,但操作复杂度远高于直接使用tmap原生多图排版功能。
内容的提问来源于stack exchange,提问作者haff
相关产品推荐
相关产品推荐

