Why is coord_sf() needed to plot a geom_raster in ggplot2 and what exactly does coord_sf() do?
According to ggplot2's Map project's documentation: coord_map projects a portion of spherical earth onto a flat, 2D plane. But why do we need this if we have transformed our data into a projected coordinate system? My second plot below uses a projected raster, but it is still stretched.
Is coord_sf() needed because geom_raster is not necessarily spatial and therefore ggplot2 would not automatically infer a projection from it as it would with geom_sf? For example, ggplot's Visualise sf objects documentation, states that geom_sf() adds coord_sf() for you (and it is therefore unnecessary to add it --i.e. it is expecting geom_sf() to spatial).
gglot2 states: crs: The CRS into which all data should be projected before plotting. If not specified, will use the CRS defined in the first sf layer in the plot. But geom_raster is a non-sf geom. So in this case, is coord_sf() when used with geom_raster() as in plot 3 below re-projecting my raster into Mercator? This would not be my assumption as it is displayed in meters. Further confounding is that when I force the ggplot2 map in plot 4 to be in EPSG 23032, the map is in degrees instead of expected meters.
library(terra)
library(ggplot2)
# Sample raster data from terra package
path_lux <- system.file("ex/elev.tif", package="terra")
f <- system.file("ex/elev.tif", package="terra")
# Create raster object, projected raster object, dataframes from each
luxembourg_elev <- terra::rast(f)
df_lux <- as.data.frame(luxembourg_elev, xy = TRUE)
luxembourg_elev_23032 <- terra::project(luxembourg_elev, y ="epsg:23032")
df_lux_23032 <- as.data.frame(luxembourg_elev_23032, xy = TRUE)
# Plot 1: geographic crs looks stretched
plot_lux <- ggplot() +
geom_raster(data= df_lux, aes(x = x, y = y, fill = elevation))
# Plot 2: projected crs still looks stretched
plot_lux_23032 <- ggplot() +
geom_raster(data= df_lux_23032, aes(x = x, y = y, fill = elevation))
# Plot 3: coord_sf() produces un-stretched plot
plot_lux_23032_coord <- ggplot() +
geom_raster(data= df_lux_23032, aes(x = x, y = y, fill = elevation)) + coord_sf()
# Plot 4: I try to specify EPSG 23032 (also no longer looks stretched but is confusingly in degrees
plot_lux_23032_2 <- ggplot() +
geom_raster(data= df_lux_23032, aes(x = x, y = y, fill = elevation)) + coord_sf(default_crs = sf::st_crs(23032))