• R语言已解决
  • 已解决:如何消除 ggplot 绘制局部世界地图时出现的冗余横线和色块?

ggplot 绘制世界地图的基本方法是这样的:

require(ggplot2)
p <- ggplot(map_data("world"), aes(long,lat,group=group)) + geom_polygon()
p

我想根据经纬度的范围来切出一块来,例如:

p + coord_map(xlim = c(-120, 40),ylim = c(30, 90))

就乱套了,有些地方出现了横跨左右的冗余横线和色块。结果图我就不贴上来了,只贴个 SO 上的类似图:

SO 上类似的讨论给出的解答只在 xlim=c(-180,180) 适用。换个小范围就不行了。

中文社区有文章详细介绍如何画地图,然而给的示例中,居然无视这个问题:

哪位不吝赐教?谢谢!

    dapengde 更改标题为「求助:如何消除 ggplot 绘制局部世界地图时出现的冗余横线和色块?

    dapengde 换投影坐标系,选一个观察角度(可选),填充颜色,图我也不贴了

    换观察角度

    worldmap <- map_data("world")
    ggplot(worldmap, aes(long, lat, group = group)) +
      geom_polygon(aes(fill = region), show.legend = FALSE) +
      coord_map(
        xlim = c(-120, 40), ylim = c(30, 90),
        orientation = c(90, 0, 0)
      )

    换投影坐标系

    ggplot(worldmap, aes(long, lat, group = group)) +
      geom_polygon(aes(fill = region), show.legend = FALSE) +
      coord_map("ortho",
        xlim = c(-120, 40), ylim = c(30, 90)
      )

    二者皆换

    ggplot(worldmap, aes(long, lat, group = group)) + 
       geom_polygon(aes(fill = region), show.legend = FALSE) +
       coord_map("ortho", xlim = c(-120, 40), ylim = c(30, 90), orientation = c(60,-80,0))

    这个问题和帖子如何放大地图的局部 <https://d.cosx.org/d/419371> 有相似之处。此外,参考 <https://ggplot2-book.org/coord.html> 末尾不同坐标变化对比,详细解释 <https://geocompr.robinlovelace.net/reproj-geo-data.html>

    从所选范围来看,北极点是比较好的观察角度

    worldmap <- map_data("world")
    
    ggplot(worldmap, aes(long, lat, group = group)) + 
       geom_polygon(aes(fill = region), show.legend = FALSE) +
       coord_map("ortho", xlim = c(-120, 40), ylim = c(30, 90), orientation = c(90,0,0))

    "ortho" 表示 orthographic() (R 的部分匹配) viewed from infinity 从无穷远点观察, 解释来自
    ?mapproj::mapproject

      Cloud2016

      我需要的是平面图而非球形图。我试了一下,其实我只需要 orientation = c(90, 0, 0) 即可:

      p + coord_map(xlim = c(-120, 40),ylim = c(30, 90), orientation = c(90, 0, 0))

      多谢!这个问题困扰我好久了。

        dapengde 更改标题为「已解决:如何消除 ggplot 绘制局部世界地图时出现的冗余横线和色块?

        dapengde 主要还是你帖子描述的比较清楚,我一看就知道是什么问题!赞发帖姿势!

          进一步比较,发现orientation = c(90, 0, 0) 对平面地图来说仍不完美。由于视角在北极,高纬度地区距离立足点较近,纬线比较稀疏,导致地图整体上纬线不均匀。这对球面来说当然更逼真,但对平面来说就不大合理了。一换视角位置,老毛病又出现了。
          如果是球面,当我想同展示一个宽广区域时,就会受限制。

          有什么办法吗?要求平面,而且经纬线均匀。@Cloud2016

            dapengde 如果是球面,当我想同展示一个宽广区域时,就会受限制

            1. 你要多宽广?举个栗子
            2. 使用球面坐标,如 "ortho" 为了好看一点
            3. 纬线不均匀,这个好理解,一方面是投影系的原因(默认的平面坐标系是墨卡托投影),一方面是观察角度的原因,需要自己去试试,诸多坐标投影我也不是很了解 @HarryZhu-7harryprince 应该有好的做法,他是专家

              Cloud2016 你要多宽广?举个栗子

              比如说,展示经度为 -140° 到 120° 范围:

              p <- ggplot(map_data("world"), aes(long,lat,group=group)) + geom_polygon()
              lr <- c(-140, 120)
              
              # 1. 如果用默认投影和默认视角,则出现冗余色块
              p + coord_map(xlim = lr)
              
              # 2. 如果用默认投影和北极视角,冗余色块是消除了,但是纬度不均匀
              p + coord_map(xlim = lr, orientation = c(90, 0, 0)) + scale_y_continuous(breaks = -9:9 * 10)
              
              # 3. 如果用球面投影 "ortho",冗余色块也消除了,纬度虽然不均匀,但显示在球面上更为自然,可是球背面就被挡住了,非洲和南美洲很难看到:
              p + coord_map("orthographic", xlim = lr)

              如何能做出纬度均匀、无冗余色块、展示宽广区域的地图呢?我这样的要求算不算太高……

                dapengde 更改标题为「虽解决,不完美:如何消除 ggplot 绘制局部世界地图时出现的冗余横线和色块?

                dapengde 用这个 geom_path()

                require(ggplot2)
                p <- ggplot(map_data("world"), aes(long,lat,group=group)) + geom_path()
                p

                  Cloud2016 geom_path() 是不行的,在 xlim = c(-140, 120)会出现冗余横线。

                  geom_path()geom_polygon() 病根儿应该是相同的,只是临床症状有区别:前者出现多余的线,后者出现多余的面。

                    Cloud2016 如果不考虑用 ggplot,那就好办了。例如用 maps 包就行:

                    maps::map("world", fill=TRUE, col="white", bg="lightblue", xlim = c(-140, 120))

                    这么说来,解决 ggplot 地图问题的方案就是不使用 ggplot 咯……

                      Liechi 这又回到了 Base R 定义的问题了: maps 包算是 Base R 吗……

                      为了避免无谓的口水战,最后可能会沦为 Tidyverse vs. Non-Tidyverse。所以可能改名叫 TNT 擂台赛。