Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I put a scalebar and a north arrow on the map (ggplot)?

I'm trying to put a scalebar and a north arrow using the package 'ggsn'. But I recive a error message:

Error: annotation_custom only works with Cartesian coordinates

In addition: Warning messages:

1: In min(data$long) : no non-missing arguments to min; returning Inf

2: In max(data$long) : no non-missing arguments to max; returning -Inf

3: In min(data$lat) : no non-missing arguments to min; returning Inf

4: In max(data$lat) : no non-missing arguments to max; returning -Inf

5: Removed 1374840 rows containing non-finite values (stat_contour).

My code is like this:

#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)

Part of my data:

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")

how can i solve this problem?

####EDIT 1

I already edited my post and now the object 'world_map' is available.

I'm having trouble using ggspatial. I loaded all the packages you mentioned and ran the command and was unable to execute the function. I went to add the package 'ggspatial', but the following message appears:

"* 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’ "

When I execute the command you requested I get the message:

Error in loadNamespace (name): there is no package called ‘ggspatial’
like image 912
Anne Elise Avatar asked May 14 '20 23:05

Anne Elise


People also ask

Do you need a north arrow on a map?

Global maps generally don't need a north arrow. Maps whose north orientation varies considerably across the layout should not have a north arrow. The need for a north arrow decreases with the audience's familiarity with the area.

What is north arrow?

A north arrow maintains a connection to a map frame and indicates the orientation of the map inside the frame. When the map rotates, the north arrow element rotates with it.

Is it possible to customize the scale bar and north arrow?

There is a library called ggsn, which allows you to customize the scale bar and north arrow. Thanks for contributing an answer to Stack Overflow! Please be sure to answer the question.

How to add a scale to a gistools map?

The function map.scale () from the maps package adds a scale. The position is in map units, latitude/longitude in this case: And GISTools north.arrow for the north arrow. Units are also in map units. This package has a map scale function as well, which looks nicer but is a little bit more complicated to set up.

Where can I find the functions for scalebar in Vue?

The functions are available on github. To install the package: From the user’s point of vue, there is only one function to use ( scaleBar ), and a few arguments to pass. However, this function has some dependencies. library (maps) library (maptools) library (ggplot2) library (grid)


1 Answers

I don't know about the ggsn package, but if you don't mind using the ggspatial package, here is an example of what I understand you're trying to achieve. Since I can't reproduce your code, I've included my own custom dataset and bathymetric data... with some nice font for a better looking final map!

# 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"
    )
  )

enter image description here

like image 174
Benoit Avatar answered Sep 26 '22 20:09

Benoit