I want to use ggpolar to plot a polar projection map of raster data, but the outermost pixels tend to obscure the land boundaries. Therefore, I want to add a local shapefile, but I failed to draw it using geom_sf in ggpolar. Even after converting the shapefile to the appropriate projection, it still couldn't be plotted. Could you please suggest a way to solve this problem? Below is my code:
continent <- st_read('F:/data/vector/seven_continent/continents/continent_30_90.shp')
ggpolar(pole = "N", max.lat = 90, min.lat = 30,
land.fill.colour = "#D9D9D9", land.outline.colour = "#343434",
plt.lat.labels = FALSE,size = 0.8) +
ggtitle("A") +
theme(plot.title = element_text(hjust = 0, family = "Arial", size = 18,face = "bold"))
+
geom_tile(data = change_ratio_df, aes(x = lon, y = lat, fill = change_ratio)) +
geom_point(data = selected_points, aes(x = lon, y = lat), color = "#343434", size =0.5) +
scale_fill_stepsn(colors = custom_colors,
breaks = break_points,
labels = c("-5", "-4", "-3", "-2", "-1", "0", "1", "2", "3", "4", "5"),
#labels = c("-0.005", "-0.004", "-0.003", "-0.002", "-0.001", "0", "0.001", "0.002", "0.003", "0.004", "0.005"),
limits = c(-6, 6),
#limits = c(-0.006, 0.006),
name = expression(AE~('%'~ decade^{-1})),
#name = NULL,
na.value = "transparent",
guide = guide_colorbar(barwidth = 0.8, barheight = unit(10, "cm"), direction = "vertical",
title.position = "right", title.hjust=0.5, label.position = "right",
title.theme = element_text(family = "Arial", size = 16, angle = 90),
label.theme = element_text(family = "Arial", size = 12)))+
geom_sf(data = continent, fill = NA, color = "#343434") +
coord_sf(crs = sf::st_crs("ESRI:102016"))+
theme(
plot.background = element_rect(fill = NA, color = NA),
panel.background = element_rect(fill = NA, color = NA),
legend.position = "none",
legend.key.width = unit(2, "line"),
legend.key.height = unit(0.5, "line"),
legend.title = element_text(family = "Arial", size = 12),
legend.text = element_text(size = 12),
axis.title = element_blank(),
axis.text = element_text(family = "Arial", size = 12),
#panel.grid.major = element_line(size=0.25,linetype='dashed',colour="black"),
axis.ticks = element_blank()
)
Here's my shapefile: https://drive.google.com/drive/folders/1tuxes8oPd_F2OmWYfPyqPjuITE0bbBBp?usp=drive_link
The following figure is without added native shapefile:
The following figure is drawn by the untransformed projection of the shapefile:
Code Error:Coordinate system already present. Adding new coordinate system, which will replace the existing one.
The following figure is plotted after the shapefile transforms the projection:
Code Error:Coordinate system already present. Adding new coordinate
I think the easiest way to handle this issue is to convert your continent sf object to a dataframe and use ggplot2::geom_path()
to plot it.
First, load required packages, create some example raster data, and load shapefile. You can safely ignore the warning that this code produces in this use case.
# remotes::install_github("EarthSystemDiagnostics/grfxtools")
library(geodata)
library(terra)
library(sf)
library(ggplot2)
library(grfxtools)
# Sample SpatRaster
r <- worldclim_global("tavg", 10, ".")
r <- r[[1]]
r <- crop(r, ext(-180, 180, 30, 90))
# Convert r to df
r_df <- as.data.frame(r, xy = TRUE)
# Load continent shapefile (assumed to be WGS84/EPSG:4326), and
# convert to multilinestring
continent <- st_read("F:/data/vector/seven_continent/continents/continent_30_90.shp") |>
st_cast("MULTILINESTRING")
# Convert to continent sf to df
line_df <- as.data.frame(st_coordinates(st_cast(continent, "LINESTRING")))
Plot:
ggpolar(pole = "N",
min.lat = 30,
max.lat = 90,
land.fill.colour = "#D9D9D9",
land.outline.colour = NA,
plt.lat.labels = FALSE,
size = 0.8) +
geom_tile(data = r_df,
aes(x, y, fill = wc2.1_10m_tavg_01)) +
geom_path(data = line_df,
aes(X, Y, group = L1),
colour = "#343434") +
theme(
plot.background = element_rect(fill = NA, color = NA),
panel.background = element_rect(fill = NA, color = NA),
legend.position = "none",
legend.key.width = unit(2, "line"),
legend.key.height = unit(0.5, "line"),
legend.title = element_text(family = "Arial", size = 12),
legend.text = element_text(size = 12),
axis.title = element_blank(),
axis.text = element_text(family = "Arial", size = 12),
axis.ticks = element_blank()
)
In the event that the linked data in the question are deleted, to make this answer a reprex here is an equivalent option using rnaturalearth
data:
library(rnaturalearth) # You may be prompted to install rnaturalearthdata
library(dplyr)
# Sample sf
sf_use_s2(FALSE)
poly_sf <- ne_countries(scale = 50) |>
summarise(geometry = st_union(geometry))
# Ensure polygon sf cropped to intended plot extent, convert to MULTILINESTRING
line_sf <- poly_sf |>
st_crop(ext(-180, 180, 30, 90)) |>
st_cast("MULTILINESTRING")
sf_use_s2(TRUE)
# Convert line_sf to df
line_df <- as.data.frame(st_coordinates(st_cast(continent, "LINESTRING")))