ggplot2(和sf)中世界地图的全地球多边形

时间:2017-04-04 12:57:59

标签: r ggplot2 gis sf

在绘制世界地图时,ggplot2存在问题:它使用相同的颜色为整个背景着色,包括实际上不是地球一部分的绘图角落,请参阅下面的快照以下代码(它使用了bleading edge sf abd ggplot2版本,但问题是通用的,请参阅下面提到的博客文章:

    #install.packages("devtools")
    #devtools::install_github("tidyverse/ggplot2")
    #devtools::install_github("edzer/sfr")

    library(ggplot2)
    library(sf)
    library(rnaturalearth)
    library(dplyr)

    theme_map <- function(...) {
      theme_minimal() +
      theme(
        text = element_text(family = "Ubuntu Regular", color = "#22211d"),
        axis.line = element_blank(),
        axis.text.x = element_blank(),
        axis.text.y = element_blank(),
        axis.ticks = element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_blank(),
        panel.grid.minor = element_line(color = "#ebebe5", size = 0.2),
        panel.grid.major = element_line(color = "#ebebe5", size = 0.2),
        plot.background = element_rect(fill = "#f5f5f2", color = NA),
        panel.background = element_rect(fill = "#f5f5f2", color = NA),
        legend.background = element_rect(fill = "#f5f5f2", color = NA),
        panel.border = element_blank(),
        ...
      )
    }

    crs <- "+proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000 +datum=WGS84 +units=m +no_defs"
    ctrys50m <- ne_countries(scale = 50, type = "countries", returnclass = "sf") %>%
       select(iso_a3, iso_n3, admin)

    ggplot() + 
      geom_sf(data = ctrys50m, alpha = 0.15, fill="grey") +
      coord_map() +
      coord_sf(crs = crs) +
      theme_map()

enter image description here

为了能够很好地绘制地球轮廓,在D3.js中添加了一个特殊的GeoJSON type{type: "Sphere"},请参阅this thread,其中可以看到here:它是以下快照中的外部整个地球黑色边框:

enter image description here

我在R / ggplot2中找到的唯一技巧是由Matt Strimas-Mackey在他的博客文章Mapping the Longest Commericial Flights in R中发布的,见{ {3}}部分以及make_bboxproject_recenter部分。

这些是相当多的代码,我想知道是否有一些 sfgeom_sf代码会生成更简洁/更简单的代码,所以我尝试了:

    # whole world WSG84 bounding box
    sphere <- ne_download(category = "physical", type = "wgs84_bounding_box", returnclass = "sf")
    sphere_laea <- st_transform(sphere, crs)
    ggplot() + 
      geom_sf(data = sphere, fill = "#D8F4FF") +
      coord_sf(crs = crs) +
      geom_sf(data = ctrys50m, alpha = 0.15, fill="grey") +
      coord_map() +
      coord_sf(crs = crs) +
      theme_map()

我得到的只是一个额外的“反子午线”(注意来自北极的线......)而没有海洋填充#D8F4FF ...... 并且多边形底部非常不规则(D3.js大师做了一些聪明的Bounding box and graticules来提高投影线的准确性......)

adaptive resampling

关于我试图获取ggplot2世界地图的整个世界多边形有什么不对的想法? (感谢你阅读这篇文章!)

2 个答案:

答案 0 :(得分:6)

根据Dave的建议,我创建了一个足够小的新网格,以便凸包操作将产生足够近似的地球边界。 以下代码给出了非常好的结果(见图后):

public String sendMail(String message, String subject, String recipientAddress,
        HttpSession session) {

    System.out.println("To:" + recipientAddress);
    System.out.println("Subject:" + subject);
    System.out.println("Message:" + message);

    try {
        SimpleMailMessage email = new SimpleMailMessage();
        email.setTo(recipientAddress);
        email.setSubject(subject);
        email.setText(message);
        mailSender.send(email);
    } catch (MailException e) {
        System.out.println("mail not sent...!" + e);
        return "noEmail";
    }
    return "success";

}

enter image description here

答案 1 :(得分:3)

我仍然在发现sf的神奇之处,因此可能会有更直接的解决方案来解决您的问题。不过,您可能会发现这种方法很有用:

为了提取地球的多边形,只需使用所需投影的刻度,创建一个凸包,并将生成的多边形联合起来。

library(ggplot2)
library(sf)
library(rnaturalearth)
library(dplyr)

crs <- "+proj=laea +lat_0=52 +lon_0=10 +x_0=4321000 +y_0=3210000
        +datum=WGS84 +units=m +no_defs"

ctrys50m <- ne_countries(scale = 50, type = "countries", returnclass = "sf") %>%
  select(iso_a3, iso_n3, admin)

sphere <- st_graticule(st_transform(ctrys50m, crs = crs)) %>%
  st_convex_hull() %>%
  summarise(geometry = st_union(geometry))

ggplot()  +
  geom_sf(data = sphere, fill = "#D8F4FF", alpha = 0.7) +
  geom_sf(data = ctrys50m, fill="grey") +
  #coord_sf(crs = crs) + # not necessary because the crs from the first layer is being used.
  theme_bw()

这为您提供了以下图表,它仍然有一些可见的角落,但根据您的目的可能就足够了。

enter image description here