【问题标题】:ggplot maps - unwanted horizontal lines when using coord_mapggplot 地图 - 使用 coord_map 时不需要的水平线
【发布时间】:2020-04-09 14:27:44
【问题描述】:

当我在 ggplot 包中使用 coord_map 时,我无法正确投影欧洲地图。下面的代码在随机位置给了我一条奇怪且不需要的水平线。有谁知道如何解决这个问题?

我不想使用coord_quickmapcoord_cartesian,因为我想保留国家的直线。

library(ggplot2)

map.world <- map_data("world")

ggplot(map.world, aes(x = long, y = lat)) + 
  geom_polygon(mapping = aes(x = long, y = lat, group = group), fill =  "#B3B1B5", color = "#D9D8DA",size = 0.4) +
  theme_minimal() +
  theme(axis.text = element_blank(), text = element_blank(), panel.grid = element_blank()) +
  coord_map(xlim = c(-27,36), ylim = c(34,67))

【问题讨论】:

  • 我得到了同样的结果。没有最后一点 - coord_map,整个世界都很好。
  • github.com/tidyverse/ggplot2/issues/3530(已关闭,无修复)
  • 似乎与coord_quickmap(...) 一起工作正常。
  • @markhogue 是的,没有coord_map 它可以很好地绘制整个世界,但我只想将地图缩放到欧洲国家。
  • @markhogue,这对我来说真的很有趣ggplot2在更改底层数据方面有什么业务?我用tracemem(map.world) 确认了它,并且在原来的ggplot(...) 中进行了更改,无论coord_mapcoord_quickmap。我还不确定这是否真的令人担忧,或者仅仅是做生意的成本......

标签: r ggplot2 maps


【解决方案1】:

有两种方法可以解决您的问题:

直截了当的方法

这种方式只需要稍微调整一下你的代码(注意我使用的是 magrittr 的转发 pipes):

library(maps)
library(magrittr)
library(maptools)
library(broom)
library(ggplot2)

europe <-  maps::map("world", fill=TRUE, plot=FALSE) %>%
                 maptools::pruneMap(xlim = c(-27,36), ylim = c(34,67))

ggplot(data= broom::tidy(europe)) + 
  geom_polygon(mapping = aes(x = long, y = lat, group = group), 
               fill =  "#B3B1B5", color = "#D9D8DA",size = 0.4) +
  theme_void() +
  coord_map()

“拥有/范围”方法

另一种解决问题的方法是使用owin 对象。这种对象将允许您创建一个空间窗口。然后,您只能在世界地图上表示此类窗口的交集。

使用这种方法,您的代码将如下所示(也使用 magrittr 的转发 pipes 并设置通用 CRS

library(maps)
library(magrittr)
library(spatstat)
library(maptools)
library(raster)
library(broom)
library(ggplot2)

#Defining a general EPSG so there won't be any superposition problems
epsg <- "+proj=longlat +datum=WGS84 +no_defs"

#Using the original maps package, then converting map into SpatialPolygons object
map.world <- maps::map("world", fill=TRUE) %$% 
  maptools::map2SpatialPolygons(., IDs=names,proj4string=CRS(epsg))

#In order to keep the names of the countries we create the following data.frame
country.labs <- sapply(slot(map.world, "polygons"), function(x) slot(x, "ID")) %>% 
  data.frame( ID=1:length(map.world), name=., row.names = .) 

#We convert object map.world into a SpatialPolygonsDataFrame object
map.world.SPDF <- sp::SpatialPolygonsDataFrame(map.world, country.labs) 

#Creating owin object using your zooming coordinates
#This step always requires to load packages 'spatstat' and 'maptools'
zoom <- as(spatstat::as.owin(c(-27,36,34,67)), "SpatialPolygons") 
raster::projection(zoom)=epsg

#Storing intersection between 'zoom' and 'world.map'
europe <- raster::intersect(map.world.SPDF, zoom)

#*country names of object europe can be accessed via europe@data

#Representing object 'europe' using broom::tidy to create a data.frame object
ggplot() + 
  geom_polygon(data = broom::tidy(europe, region="name"), 
               mapping = aes(x = long, y = lat, group = group), 
               fill =  "#B3B1B5", color = "#D9D8DA",size = 0.4) +
  theme_void() +
  coord_map()

#*country names after tidying 'europe' this way are in a new column called 'id'

根据你在做什么,你可能想要使用

zoom <- as(raster::extent(c(-27,36,34,67)), "SpatialPolygons")

创建一个extent对象而不是一个owin对象(这里的结果是一样的)

下面显示任何方法得到的结果

如果您需要进行不同的缩放,您可以轻松地将任何替代方法封装在一个函数中。

希望对你有帮助

BONUS BALL:查看tmap 包对您来说可能会很有趣

【讨论】:

  • 谢谢你,你是救生员!还有一件事 - 我可以做些什么来保留对象 tidy(europe) 中的国家名称?
  • 我将编辑我的答案,以便对象 europe 包含国家/地区的名称
  • 谢谢,非常感谢
  • 我很高兴它有帮助:)
  • 借助 maptools::pruneMap 功能,我添加了一种更直接的方式来完成您想要的工作:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-16
  • 2012-03-21
  • 1970-01-01
  • 2018-04-16
  • 2021-05-06
  • 1970-01-01
相关资源
最近更新 更多