如何在地图上放置比例尺和指北针(ggplot)?

Posted

技术标签:

【中文标题】如何在地图上放置比例尺和指北针(ggplot)?【英文标题】:How can I put a scalebar and a north arrow on the map (ggplot)? 【发布时间】:2020-08-31 16:44:16 【问题描述】:

我正在尝试使用“ggsn”包放置比例尺和指北针。 但我收到一条错误消息:

错误:annotation_custom 仅适用于笛卡尔坐标

另外:警告信息:

1:在 min(data$long) 中:min 没有非缺失参数;返回Inf

2:在 max(data$long) 中:max 没有非缺失参数;返回 -Inf

3:在 min(data$lat) 中:min 没有非缺失参数;返回Inf

4:在 max(data$lat) 中:max 没有非缺失参数;返回 -Inf

5:删除了 1374840 行包含非有限值 (stat_contour)。

我的代码是这样的:

#loading the map
world <- maps::map("world2", fill=TRUE, plot=FALSE) # world2 is the Pacific centered map with longitude [0,360]

IDs <- sapply(strsplit(world$names, ":"), function(x) x[1])
world <- map2SpatialPolygons(world, IDs=IDs, proj4string=CRS("+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"))

world_map <- fortify(world)

#load the bathymetry 
bat <- marmap::getNOAA.bathy(lon1 = -5.0000, lon2 = -80.0000, lat1 = 14, lat2 = -70.61, keep=T) 

#converting the bathymetry in data.frame
bat2 = marmap::fortify.bathy(bat) 

g <- ggplot(AR, aes(x = lon, y = lat)) + #(old: Longitude #Latitude)
 geom_path(aes(group = sex, col = sex), size = 0.8, alpha = 0.5) +
 geom_map(data = world_map, map=world_map, aes(x = long, y = lat, map_id = id), fill = "darkgray") +
  geom_contour(data = bat2, 
               aes(x=x, y=y, z=z),
               breaks=c(-200),
               size=c(0.3),
               colour="blue")+
  xlim(extendrange(AR$lon, f = 0.1)) + #(old: Longitude)
  ylim(extendrange(AR$lat, f = 0.1)) + #(old: Latitude)
  coord_map("ortho", orientation = c(-40, -40, 0))

g +
  ggsn::scalebar(world_map, dist = 100,location = "bottomright", transform = TRUE, #Adicione uma barra de escala
                 dist_unit = "km", st.dist = 0.03, st.size = 2, model = 'WGS84') +
  ggsn::north(world_map, scale = .1)

我的部分数据:

structure(list(lon = c(-38.8745, -38.8676, -38.9445, -38.9811, 
-38.9322, -38.9386), lat = c(-14.09437, -14.25664, -14.34518, 
-14.51857, -14.95994, -15.41684), bmode = c(1.396, 1.375, 1.346, 
1.248, 1.074, 1.289), bmode.5 = c(1, 1, 1, 1, 1, 1), ID = structure(c(53L, 
53L, 53L, 53L, 53L, 53L), .Label = c("10946.05", "20162.03", 
"21792.03", "21800.03", "21810.03", "24640.03", "24641.05", "24642.03", 
"27258.05", "27259.03", "27261.03", "27261.05", "27261.07", "33000.05", 
"37231.07", "37234.05", "37288.07", "42521.07", "50682.07", "50687.07", 
"60004.07", "81122.09", "81123.09", "81124.09", "81125.09", "81126.09", 
"84497.1", "87632.12", "87759.08", "87761.08", "87762.08", "87763.08", 
"87764.08", "87765.08", "87766.08", "87768.08", "87768.11", "87769.11", 
"87770.08", "87773.08", "87773.1", "87773.11", "87774.09", "87774.11", 
"87775.08", "87776.08", "87776.11", "87777.1", "87778.08", "87783.09", 
"88724.1", "88727.09", "111868.11", "111871.12", "112702.12", 
"112712.12", "112714.12", "120947.12", "121189.12", "121192.12", 
"121196.12", "1211931.12"), class = "factor"), sex = structure(c(3L, 
3L, 3L, 3L, 3L, 3L), .Label = c("F", "Fc", "M"), class = "factor"), 
    speed = c(0.921691675, 2.990097297, 2.137609076, 3.259383146, 
    8.173674567, 8.413534172), area = structure(c(3L, 3L, 3L, 
    3L, 3L, 3L), .Label = c("AA", "AM", "AR"), class = "factor"), 
    angulo = c(41.027, -43.41, 29.056, 18.241, -7.125, -4.702
    ), angle_rel = c(0.7160619, -0.7576522, 0.5071251, 0.3183724, 
    -0.1243479, -0.08206201), bat.depth = c(-45L, -397L, -32L, 
    -29L, -21L, -3L), dist = c(5.53015005, 17.94058378, 12.82565446, 
    19.55629887, 49.0420474, 50.48120503), angulo_modulo = c(41.027, 
    43.41, 29.056, 18.241, 7.125, 4.702), curva = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L), .Label = c("curva", "reta"), class = "factor")), row.names = 2:7, class = "data.frame")

我该如何解决这个问题?

####EDIT 1

我已经编辑了我的帖子,现在可以使用对象“world_map”。

我在使用 ggspatial 时遇到问题。 我加载了您提到的所有软件包并运行了命令,但无法执行该功能。 我去添加包'ggspatial',但出现以下消息:

"* installing * source * package 'ggspatial' ...
** package 'ggspatial' successfully unpacked and MD5 sums checked
** R
** inst
** byte-compile and prepare package for lazy loading
Error: .onLoad failed in loadNamespace () for 'sf', details:
  call: get (genname, envir = envir)
  error: object 'group_split' not found
ERROR: lazy loading failed for package 'ggspatial'
* removing 'C: /Users/annel/OneDrive/Documentos/R/win-library/3.5/ggspatial'
In R CMD INSTALL
Warning in install.packages:
  installation of package ‘ggspatial’ had non-zero exit status

The downloaded source packages are in
‘C: \ Users \ annel \ AppData \ Local \ Temp \ RtmpKueyQV \ downloaded_packages’ "

当我执行您请求的命令时,我会收到以下消息:

Error in loadNamespace (name): there is no package called ‘ggspatial’

【问题讨论】:

我无法重现您的代码,因为我假设dput 输出是针对AR,但是,您没有提供对象world_map。不管怎样,ARworld_map 都不见了。 @IanCampbell 我编辑了我的帖子。谢谢! 【参考方案1】:

我不知道ggsn 包,但如果您不介意使用ggspatial 包,这里是我理解您正在尝试实现的示例。由于我无法重现您的代码,因此我已经包含了我自己的自定义数据集和测深数据...带有一些漂亮的字体以获得更好看的最终地图!

# Load necessary packages
library(tidyverse)
library(ggrepel)
library(sf)
library(marmap)

# Create random data
fake_data <- tibble(
  Latitude = c(45.36, 46.74, 45.35, 45.28, 45.21, 45.92, 43.83, 46.80, 43.70, 43.97),
  Year = factor(c(2010, 2010, 2010, 2010, 2010, 2007, 2008, 2008, 2008, 2008)),
  Longitude = c(-2.64, -3.33, -3.22, -2.77, -2.54, -2.69, -1.99, -2.71, -1.68, -2.16),
  Lab = c("960", "950", "956", "962", "961", "768", "865", "848", "866", "860")
)

# Transform data points into geographic objects
Sites_geo <- fake_data %>%
  st_as_sf(coords = c("Longitude", "Latitude"), crs = 4326)

# Get bathymetry data
bathy <- getNOAA.bathy(-8, 0, 42, 50, res = 1, keep = TRUE)
ggbathy <- fortify(bathy)

# Get countries outline
pays <- rnaturalearth::ne_countries(
  country = c("France", "Spain"),
  scale = "large", returnclass = "sf"
)

# Base plot
pl <- ggplot(data = pays) +
  geom_contour(
    data = ggbathy, aes(x = x, y = y, z = z),
    binwidth = 200, color = "grey80", size = 0.3
  ) +
  geom_contour(
    data = ggbathy, aes(x = x, y = y, z = z),
    binwidth = 1000, color = "grey60", size = 0.4
  ) +
  geom_sf() +
  geom_sf(data = Sites_geo, aes(fill = Year), shape = 21) +
  geom_text_repel(
    data = fake_data, aes(x = Longitude, y = Latitude, label = Lab),
    force = 3, family = "ArcherPro Book"
  ) +
  coord_sf(xlim = c(-6, 0), ylim = c(43, 48.5), expand = FALSE) +
  scale_fill_viridis_d() +
  labs(x = "", y = "", fill = "Year") +
  theme_bw(base_family = "ArcherPro Book")

# Add scale and North arrow
pl +
  ggspatial::annotation_scale(
    location = "tr",
    bar_cols = c("grey60", "white"),
    text_family = "ArcherPro Book"
  ) +
  ggspatial::annotation_north_arrow(
    location = "tr", which_north = "true",
    pad_x = unit(0.4, "in"), pad_y = unit(0.4, "in"),
    style = ggspatial::north_arrow_nautical(
      fill = c("grey40", "white"),
      line_col = "grey20",
      text_family = "ArcherPro Book"
    )
  )

【讨论】:

您好,感谢@Benoit 的回答。我现在有另一个问题,你能帮我解决这个问题吗?我会和他们一起编辑我的帖子。 @AnneElise 如果您认为这回答了您的问题,您可能需要考虑通过检查它旁边的勾号来接受它 - 谢谢! @AnneElise 您似乎尝试从源代码安装ggspatial。您是否尝试过安装二进制包? install.packages("ggspatial", type = "binary") @Benoit 我没听懂。我按照你说的安装了包,并且我的地图中插入了指北针,但我仍在尝试将它定位在正确的位置。比例尺仍然出现错误。完成编辑后,是否无法帮助尝试使用我的数据制作地图?对不起,对这个主题的无知。这张地图在我的工作中非常重要,我已经尝试了一段时间。【参考方案2】:

使用您的数据(存储在名为 ARdata.frame 中)并尝试匹配您想要的输出,这是我的建议:

# Load necessary packages
library(tidyverse)
library(sf)
library(marmap)

# Import AR data

# Transform data points into geographic objects
Sites_geo <- AR %>%
  st_as_sf(coords = c("lon", "lat"), crs = 4326)

# Get bathymetry data: please note I zoomed on the area of interest
# to get a more manageable dataset. If you want a larger area,
# you should increase res (e.g. res = 10) in order to get a
# bathy object of a reasonable size
bathy <- getNOAA.bathy(-45, -30, -20, -5, res = 4, keep = TRUE)
# load the bathymetry 
ggbathy <- fortify(bathy)

# Get countries outline
pays <- rnaturalearth::ne_countries(
  country = c("Brazil"),
  scale = "large", returnclass = "sf"
)

# Base plot
pl <- ggplot(data = pays) +
  geom_contour(
    data = ggbathy, aes(x = x, y = y, z = z),
    binwidth = 200, color = "grey90", size = 0.3
  ) +
  geom_contour(
    data = ggbathy, aes(x = x, y = y, z = z),
    binwidth = 1000, color = "grey70", size = 0.4
  ) +
  geom_sf() +
  geom_sf(data = Sites_geo, aes(fill = speed), shape = 21) +
  geom_path(data = AR, aes(x = lon, y = lat, group = sex, col = sex)) +
  coord_sf(xlim = c(-42, -30), ylim = c(-20, -5), expand = FALSE) +
  scale_fill_viridis_c() +
  labs(x = "", y = "", color = "Sex") +
  theme_bw(base_family = "ArcherPro Book")

# Add scale and North arrow
pl +
  ggspatial::annotation_scale(
    location = "tl",
    bar_cols = c("grey60", "white"),
    text_family = "ArcherPro Book"
  ) +
  ggspatial::annotation_north_arrow(
    location = "tl", which_north = "true",
    pad_x = unit(0.4, "in"), pad_y = unit(0.4, "in"),
    style = ggspatial::north_arrow_nautical(
      fill = c("grey40", "white"),
      line_col = "grey20",
      text_family = "ArcherPro Book"
    )
  )

这会产生以下地图:

比例尺和指北针的位置由 ggspatial 包中的 annotation_scale()annotation_north_arrow() 函数的 locationpad_xpad_y 参数控制。

这能解决您的问题吗?

【讨论】:

以上是关于如何在地图上放置比例尺和指北针(ggplot)?的主要内容,如果未能解决你的问题,请参考以下文章

数据可视化应用绘制空间地图(附R语言代码)

arcmap如何制图

ArcGIS Engine添加地图元素的实现

ArcGIS Engine添加地图元素的实现

怎么在ARCGIS中国地图上画线

arcmap如何制图