Alternative to map_data('world') - Covers Antartica to -90 - r

I am looking for a simple alternative to map_data('world') as a data set with which to easily draw the countries of the world. Ideally it's easily implementable with ggplot2.
The problem is that I am graphing some geographic points, some of which appear close to -90 (S). When I use map_data('world') to get my polygons, I see that Antarctica doesn't run all the way to -90 (lowest lat value for Antarctica is -85.19218 - see code below). Thus anything further south than that shows as if its off the map, which doesn't look great.
Here is an example of what I am talking about:
library('ggplot2') #Import library
world = map_data('world') #Get polygon data
data = data.frame(lat = -86, long = 0) #Create geographic data with southerly value
#plot
ggplot() +
geom_polygon(data = world,
aes(y = lat, x = long, group = group), col = 'grey', fill = NA) +
geom_point(data = data,
aes(y = lat, x = long), col = 'red')
Gives:
You can see the limits of the Antarctic extent as follows:
library('dplyr')
world %>%
filter(region == 'Antarctica') %>%
select(lat) %>%
min()
[1] -85.19218
Thus the problem is not the projection, its the data set. Does anyone know an alternative easily available rendering of the countries that has Antarctica running to -90?

There isn't any data for ggplot2 to plot below about 85 degrees south in the world data as a polygon. Using geom_polygon also has the drawback of connecting the data from the far left (west) to the data on the far right(east).
To get around having the straight line above the red dot, use the sf package and geom_sf to plot spatial data.
I don't know of a good way to plot Antarctica along with the entire rest of the globe. If you are mostly interested in the southern pole & it's surroundings, an orthographic projection might work.
library(tidyverse)
library(rnaturalearth)
world <- map_data('world') #Get polygon data
data = data.frame(lat = -86, long = 0) #Create geographic data with southerly value
#plot
p_polygon <- ggplot() +
geom_polygon(data = world,
aes(y = lat, x = long, group = group), col = 'grey', fill = NA) +
geom_point(data = data,
aes(y = lat, x = long), col = 'red')
# use rnaturalearth package to get coastline data in the sf format
world_sf <- ne_coastline(returnclass = 'sf')
# use geom_sf to plot the data
p_sf <- ggplot(world_sf) +
geom_sf() +
geom_point(data = data, aes(y = lat, x = long), col = 'red')
# geom_sf, using an orthographic projection
p_sf_ortho <- ggplot(world_sf) +
geom_sf() +
geom_point(data = data, aes(y = lat, x = long), col = 'red') +
coord_sf( crs= "+proj=ortho +lat_0=-80 +lon_0=90")
# the three plots together
cowplot::plot_grid(p_polygon, p_sf, p_sf_ortho,
labels = c('polygon', 'sf', 'sf orthographic'))
Created on 2021-08-27 by the reprex package (v0.3.0)

The {rnaturalearth} package has a good representation of Antarctica (and the other land masses too!) I have switched to using it for all my background mapping. This example:
world <- rnaturalearth::ne_countries(returnclass = "sf")
map_crs <- st_crs(3031) # WGS 84 / Antarctic Polar Stereographic
ggplot() + geom_sf(data = world %>% st_transform(map_crs)) +
coord_sf(datum = map_crs,
ylim = c(-3e6,3e6),
xlim = c(-3e6,3e6))
Produces this map - there is just a tiny sliver of unmapped Antarctica:

Related

How do I implement geom_path on a sf object containing GPS location data mapped using ggplot2

I need to create path trajectory using GPS location data collected at 15 minute intervals from an animal. The base map is created using a ggplot and the sf package. Here is the code and a snippet of the data.
# Libraries
library(tidyverse)
library(sf)
# GPS data
gps_6067 = data.frame(DT_UTC = as.POSIXct(c('2020-07-08 00:00:08', '2020-07-08 00:15:08', '2020-07-08 00:30:08', '2020-07-08 00:45:08', '2020-07-08 01:00:09', '2020-07-08 01:15:09', '2020-07-08 01:30:08', '2020-07-08 01:45:09', '2020-07-08 02:00:39', '2020-07-08 02:15:10'), format = '%Y-%m-%d %H:%M:%S'),
Lat = c(44.21540, 44.21525, 44.21497, 44.21506, 44.21514, 44.21525, 44.21560, 44.21552, 44.21534, 44.21526),
Lon = c(-87.20221, -87.20262, -87.20264, -87.20298 ,-87.20318, -87.20343, -87.20360, -87.20365, -87.20353, -87.20391))
So now we have the data, I can make a ggplot showing the path connecting temporally sequential gps locations
ggplot(data = gps_6067, aes(x = Lon, y = Lat))+
geom_point()+
geom_path()
Now, I need to plot this on top of a raster and other spatial data, which I am using the sf package for.
# Create an sf spatial object
gps_6067.sf = st_as_sf(gps_6067,
coords = c("Lon", "Lat"),
crs = crs("+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"),
remove = F)
# So far so good, and it plots like it would be expected to
# Plot the points using ggplot
ggplot()+
geom_sf(data = gps_6067.sf, size = 1.5, aes(color = DT_UTC))+
scale_color_datetime(low = 'orange', high = 'green')
This works, but I need to add a path layer to the new map
ggplot()+
geom_sf(data = gps_6067.sf, size = 1.5, aes(color = DT_UTC))+
scale_color_datetime(low = 'orange', high = 'green')+
geom_path(data = gps_6067.sf)
I know that I have to specify the crs to the geom_path command, but I haven't seen it implemented. Any insight is appreciated!!!!
Try adding:
ggplot()+
geom_sf(data = gps_6067.sf, size = 1.5, aes(color = DT_UTC))+
scale_color_datetime(low = 'orange', high = 'green')+
geom_path(data = gps_6067.sf, aes(x = Lon, y = Lat))
This will connect the points and create the path.
I believe you mentioned something about a raster? Do you have sample code for that?
Generally, to add a raster layer to a plot I would convert it to data.frame and use geom_tile.
example
library(dplyr)
library(terra)
r <- rast('path_to_raster.tif') %>% as.data.frame(xy=T)
# Check the name of column you want to use as color
names(r)
ggplot() +
geom_tile(data = r, aes(x = x, y = y, fill = <colName>)) +
geom_sf(data = GPS etc...) # this part you already have

Mapping geom-cordinates to a map object in R

I am attempting to map some geom-points/cordinates to a map of the country Sri Lanka. I am able to map the district borders, and the population as expected, but I am having trouble plotting the geom points onto the map.
Install package
devtools::install_github("thiyangt/ceylon")
Load package
library("ceylon")
library(tidyverse)
library(sp)
library(viridis)
data(sf_sl_0)
Mapping only Sri Lanka
ggplot(sf_sl_0) + geom_sf()
Mapping the districts of Sri Lanka + population
ggplot(district) + geom_sf(aes(fill = population), show.legend = TRUE) + scale_fill_viridis()
Mappping specific geom-cordinates onto the map of Sri Lanka districts
These are the cordinates I want to map (yes, they are definitely within SL)
df_cord <- data.frame (lat = c("6.2441521", "6.2234515"),
lon = c("80.0590804", "80.2126109"))
I tried:
ggplot(district) +
geom_sf(df_cord) + scale_fill_viridis() +
geom_point(
data = df_cord,
aes(x = lon, y = lat),
size = 4,
shape = 23,
fill = "darkred"
)
But I get an error: Error in validate_mapping():
! mapping must be created by aes()
It looks like I might need to find the x,y cordinates of every geom point, and then map it with cord_sf? But I am not having an luck figuring out how to do this. I found a cool function called usmap::usmap_transform, which converts US geom points to x,y cordinates... but I can't figure out how to do the same for this map of Sri Lanka.
I am very new to mapping -- could someone please advise? Many thanks! I am open to other approaches/solutions!
One way would be to convert the coordinates to an sf object using st_as_sf and plot them using geom_sf. Don't forget to reproject the data to the same coordinate sistem:
library(ceylon)
library(tidyverse)
library(sp)
library(viridis)
library(sf)
data(district)
df_cord <- data.frame (lat = c(6.2441521, 6.2234515),
lon = c(80.0590804, 80.2126109))
df_cord <- df_cord %>%
st_as_sf(coords = c("lon", "lat"), crs = 4326) %>%
st_transform(crs = st_crs(district)) #reproject coords using the coordinate system of the polygons
#plot
ggplot(district) +
geom_sf(aes(fill = population), show.legend = TRUE) +
geom_sf(data = df_cord ,
size = 4,
shape = 23,
fill = "darkred") +
scale_fill_viridis()
I think you can't assign two data frames in ggplot.
Put the latitude and longitude values ​​inside the geom_point's aes(). Remember that longitude is the x-axis and latitude is the y-axis.
Try this:
ggplot() +
geom_sf(district) +
scale_fill_viridis() +
geom_point(
aes(x = c("80.0590804", "80.2126109"),
y =c("6.2441521", "6.2234515")),
size = 4,
shape = 23,
fill = "darkred"
)
You can add annotations (annotate) which will display your two coordinates. Also, set the right coordinate system like this:
ggplot(district) +
geom_sf(aes(fill = population), show.legend = TRUE) +
annotate("point", x = 80.0590804, y = 6.2441521, colour = "red", size = 2) +
annotate("point", x = 80.2126109, y = 6.2234515, colour = "red", size = 2) +
coord_sf(default_crs = sf::st_crs(4326)) +
scale_fill_viridis()
Output:

Subsetting a shapefile

I have a shapefile here: https://login.filesanywhere.com/fs/v.aspx?v=8c6c63865a6574bcaa69
I have a shapefile of California red legged frog that I am overlaying on top of California, however, the range of these frogs extends outside of California and going into Mexico. I only want the frog data from California, how can I trim data extending into Mexico? I tried to use subset to separate the 'ORIGIN' but it doesn't seem to have any effect. Thanks for any help beforehand..
library(rgdal)
library(tidyverse)
ranas <- readOGR(dsn = ".", layer = "data_0")
names(ranas)
# Coerce into a dataframe
ranas4 <- fortify(ranas)
head(ranas4)
cali_map <- map_data("state",region="california")
counties <- map_data("county",region="California")
head(counties)
windows(w=9)
ggplot(cali_map, aes(x = long, y = lat, group = group)) +
geom_polygon() +
geom_polygon(data = ranas4, fill = "green")
ggplot(cali_map, aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "cornsilk4", col = "cornsilk") +
geom_polygon(data=counties,color="black",fill="lightgoldenrod") +
geom_polygon(data = ranas4, fill = "green", alpha = 0.5) +
theme_void() +
theme(panel.background = element_rect(fill = "cornsilk")) +
coord_map("albers",lat=90,lat1=80)
# Tried to trim data outside California (Mexico data) with no success.
#I tried:
ranas2 <- subset(ranas,ORIGIN !=1)
but it doesn't have any effect or subsets anything.
Subsetting your spatial dataframe won't be of much use, because neither of its features (rows) is entirely within California:
## plot features by origin:
library(ggplot2)
library(sf)
my_shp <- read_sf(dsn = "path_to_shp_directory")
my_shp %>%
ggplot() +
geom_sf() +
facet_wrap(~ ORIGIN)
You can still crop (clip) a feature with California's boundaries ...:
## make sure both geometries have the same CRS,
## if necessary, by st_transform(your_epsg_code)
my_shp_cropped <- st_crop(my_shp, cali_map)
... but note that won't recalculate the underlying frog data (e.g. frog count in California only).

King County map not displaying the boundaries correctly

Hi I'm trying to plot the map of King County in Washington because I'm having few data points which need to be placed in the map. The following is what I used.
long <- c(47.5112,47.7210 ,47.3684,44)
lat <- c(-122.257, -122.319, -122.031,-120)
price <- c(287655,456355,662500,234563)
House <- data.frame(long, lat, price)
states <- map_data("state")
# west_coast <- states %>%
# filter(region %in% c("washington"))
wa_df <- states %>%
filter(region == "washington", subregion == 'king')
counties <- map_data("county")
wa_county <- counties %>%
filter(region == "washington", subregion == 'king')
wa_base <-
ggplot(data = wa_df,
mapping = aes(x = long, y = lat, group = group)) +
geom_point(
data = House,
mapping = aes(x = long, y = lat),
color = "red",
inherit.aes = FALSE
) +
coord_fixed(1.3) +
geom_polygon(color = "black", fill = "gray")
#geom_point(data = House, mapping = aes(x = long, y = lat), color = "red")
wa_base + theme_nothing() +
geom_polygon(data = wa_county, fill = NA, color = "black") +
geom_polygon(color = "black", fill = NA) # get the state border back on top
The following is the map I received. I do not find that the map looks good. Please help
I am new to R and this is my first response, but I might have found a solution to this problem. The boundaries downloaded from the maps package are not exact. You can download correct boundary data as a shapefile here: https://gis-kingcounty.opendata.arcgis.com/datasets/kingcounty::king-county-political-boundary-no-waterbodies-kingco-area/explore?location=47.477749%2C-121.920728%2C9.83
Use:
library(ggmap)
library(mapdata)
library(rgdal)
library(tidyverse)
After that, read the shapefile into R and use map_data() to convert it into a data frame:
kc_bound <- readOGR(dsn="~/Desktop/King_County",layer="King_County_Political_Boundary_(no_waterbodies)___kingco_area")
kc_bound_df <- map_data(kc_bound)
Assuming that you also work on the house price prediction data set from kaggle (https://www.kaggle.com/harlfoxem/housesalesprediction) you can run the following code to get a plot of the houses with the King County boundary around it (df is your data frame):
ggplot() + geom_point(df,mapping=aes(x=long,y=lat),color="red") + geom_polygon(kc_bound_df,mapping=aes(x=long,y=lat),fill=NA, color="black")
See this picture for the result: Houses in King County plotted with county boundary
Hope this helps, let me know what you think!

Plot of Russia split in two

I am trying to plot Russia from a shp-file, but Russia always comes up as in two parts. How do I get Russia back together in one piece?
I have tried several shp-files e.g.
http://www.naturalearthdata.com/downloads/10m-cultural-vectors/
Admin 1 – States, Provinces ; Download without large lakes (14.11 MB) version 3.0.0
shp <- readOGR("ne_10m_admin_1_states_provinces_lakes.shp")
Subset to Russia
names(shp)
rus <- shp[shp$admin == "Russia" , ]
x11()
plot(rus)
Since you want to plot it, you can fortify the shapefile to data frame, modify the longitude coordinates in the -180 region, & plot the result in ggplot:
library(rgdal); library(ggplot2)
# read in the shapefile & subset to Russia
shp <- readOGR(dsn = "ne_10m", layer = "ne_10m_admin_1_states_provinces_lakes")
rus <- shp[shp$admin == "Russia", ]
# fortify to data frame & modify longitude coordinates in the -180 region.
rus.fortify <- fortify(rus) %>%
mutate(long = ifelse(long < -100, long + 180*2, long))
# plot to verify
ggplot(rus.fortify,
aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "white", col = "black") +
coord_map() #default projection is mercator
I've also just learned from this post that you can specify different projection systems. Given how large Russia is, this ought to be relevant:
ggplot(rus.fortify,
aes(x = long, y = lat, group = group)) +
geom_polygon(fill = "white", col = "black") +
coord_map("azequalarea")

Resources