Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No error reported but not displayed when using crs and default_crs parameter in coord_sf #6382

Open
Breeze-Hu opened this issue Mar 27, 2025 · 10 comments · May be fixed by #6383
Open

No error reported but not displayed when using crs and default_crs parameter in coord_sf #6382

Breeze-Hu opened this issue Mar 27, 2025 · 10 comments · May be fixed by #6383
Labels
coord 🗺️ messages requests for improvements to error, warning, or feedback messages

Comments

@Breeze-Hu
Copy link

Breeze-Hu commented Mar 27, 2025

Hi, I'm using ggplot to process some geospatial data and I'm finding that setting crs and default_crs doesn't produce the expected results and no errors are reported.
I'm not sure if it's because I don't fully understand these two parameters or if it's something else.

  • crs is supposed to determine the reference system for the final plot;
  • default_crs is used to specify the original reference system for the data.

In the example below, the raw data is in the epsg:4326 coordinate system, and I'm trying to show it using a different projected coordinate system, but the plotting results are blank.

I provided data that could be reproduced: example data

library(ggplot2)
library(sf)

data <- read.csv('./example.csv', row.names = 1)

targetcrs <- paste(
  "+proj=lcc", 
  "+lat_1=25", 
  "+lat_2=47", 
  "+lon_0=105", 
  "+datum=WGS84", 
  "+units=m", 
  sep = " "
)

ggplot(data = data, aes(x = x, y = y))+
  geom_raster(aes(fill = value))+
  facet_wrap(~class)+
  coord_sf(
    crs = st_crs('epsg:32649'), # or crs = targetcrs,
    default_crs = st_crs('epsg:4326'))
Image
@teunbrand
Copy link
Collaborator

teunbrand commented Mar 27, 2025

Thanks for the report! The issue is here is that you're trying to use geom_raster() for a non-Cartesian coordinate system. The problem would be solved by using geom_tile() instead. That said, geom_raster() should emit the intended message about it being coerced to geom_rect() and produce some graphic, as introduced in #5627.

@Breeze-Hu
Copy link
Author

Breeze-Hu commented Mar 27, 2025

Oh, sorry! That came across as a bit of an idiotic question. hahahaha

Although there was no mapping, there were no warning messages sent.

> ggplot(data = data, aes(x = x, y = y))+
+   geom_raster(aes(fill = value))+
+   facet_wrap(~class)+
+   coord_sf(#crs = targetcrs,
+     crs = st_crs('epsg:32649'),
+     default_crs = st_crs('epsg:4326'))
> 

Using geom_tile() does achieve roughly the same result. But there will be tiny borders, colour = NA doesn't seem to work.

Image

@teunbrand
Copy link
Collaborator

teunbrand commented Mar 27, 2025

Yeah to reduce anti-aliasing artefacts you can use the following mapping: aes(fill = value, colour = after_scale(fill), linewidth = I(0.3)).

@Breeze-Hu
Copy link
Author

Great work! Thanks! : )

@teunbrand teunbrand added messages requests for improvements to error, warning, or feedback messages coord 🗺️ labels Mar 27, 2025
@Breeze-Hu
Copy link
Author

Oh, and it suddenly occurred to me that both pieces of information are very useful. But it doesn't seem to be reflected in the documentation? (Or maybe I'm just not seeing it...) ggplot stable and ggplot dev If not, could it be added to the docs by the way, I'm sure it'll prevent anyone else from asking the same not-so-clever question as me. hhhhhh

The issue is here is that you're trying to use geom_raster() for a non-Cartesian coordinate system. The problem would be solved by using geom_tile() instead.

and

to reduce anti-aliasing artefacts you can use the following mapping: aes(fill = value, colour = after_scale(fill), linewidth = I(0.3)).

@Breeze-Hu
Copy link
Author

Breeze-Hu commented Mar 28, 2025

#6383 (comment)

ggplot(data = data, aes(x = x, y = y))+
  geom_raster(aes(fill = value))+
  facet_wrap(~class)+
  coord_sf(
    crs = st_crs('epsg:32649'),
    default_crs = st_crs('epsg:4326')
  )
#> `geom_raster()` only works with `coord_cartesian()`.
#> ℹ Falling back to drawing as `geom_rect()`.
#> `geom_raster()` only works with `coord_cartesian()`.
#> ℹ Falling back to drawing as `geom_rect()`.
#> `geom_raster()` only works with `coord_cartesian()`.
#> ℹ Falling back to drawing as `geom_rect()`.

Falling back to drawing as geom_rect() : A warning message is provided, but a plotting result is given. Is this result accurate compared to geom_tile?

Is the width, and height or xmin, xmax, ymin, ymax parameters calculated invisibly so as to avoid the width/2 offset? If not, then the result will be misleading to the user (They don't realise that the coordinate correspondence of the raster data is wrong). With my very weak coding skills, it seems to be calculated in the background before drawing.

But if the result is correct, is geom_tile unnecessary?.... I'm in a confusion.

@teunbrand
Copy link
Collaborator

The anti-aliasing properties are device dependent, so the trick to avoid phantom lines are not universal.

Falling back to drawing as geom_rect() : A warning message is provided, but a plotting result is given. Is this result accurate compared to geom_tile?

It should be similar. I can't spot any difference by eye.

Is the width, and height or xmin, xmax, ymin, ymax parameters calculated invisibly so as to avoid the width/2 offset?

I'm not sure what you mean by this. How does the width/2 offset come into play?

But if the result is correct, is geom_tile unnecessary?

No, geom_raster() specificallly is an optimised case for when you have cells in a straight, axis-aligned grid with equal widths for all columns and equal heights for all rows. If these assumptions are broken, the user should use geom_tile() or geom_rect() as it makes no sense to use raster optimisation. The message that is thrown is meant to annoy users into swapping out geom_raster(), which is what should happen.

@Breeze-Hu
Copy link
Author

I'm not sure what you mean by this. How does the width/2 offset come into play?

Sorry! It does seem a bit unclear, probably means something like:
x and y are the central coordinates of the raster.

df <- expand.grid(x = 0:5, y = 0:5)
set.seed(1)
df$z <- runif(nrow(df))

ggplot(df, aes(x, y, fill = z)) +
  geom_raster() +
  coord_sf(crs = st_crs('epsg:4326'))

#  In order to complete the drawing, falling back like : 
ggplot(df, aes(x, y, fill = z)) +
  geom_rect(aes(width = 1, height = 1)) +  # aes(width = 1, height = 1)  is calculated in the background
  coord_sf(crs = st_crs('epsg:4326'))

If these assumptions are broken, the user should use geom_tile() or geom_rect() as it makes no sense to use raster optimisation. The message that is thrown is meant to annoy users into swapping out geom_raster(), which is what should happen.

So geom_raster fallback to geom_rect gives the correct result, the warning given still expects the user to use either geom_tile or geom_rect for plotting, as in the case of using regular and aligned spatial raster data.

@teunbrand
Copy link
Collaborator

Yeah rasters already calculate the 4 sides of a cell to correctly place the 4 corners of the raster, so it naturally expands to data compatible with geom_rect().

So geom_raster fallback to geom_rect gives the correct result

Well it gives the correct result in terms of data visualisation, it does not give the correct result in terms of 'the user requests a raster' for which there can be various intentions. A raster has a smaller file size footprint than polygons/rectangles and can interpolate cells, which are both valid reasons to prefer a raster over rectangles.

@Breeze-Hu
Copy link
Author

Breeze-Hu commented Mar 28, 2025

A raster has a smaller file size footprint than polygons/rectangles and can interpolate cells, which are both valid reasons to prefer a raster over rectangles.

Yeah, for those who do spatial data analysis (including spatial data visualisation) will naturally be more receptive to raster, and the presentation of interpolated data will be easier.
Your work is already important, and this is the suitable solution for the moment.

Thanks for your great work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
coord 🗺️ messages requests for improvements to error, warning, or feedback messages
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants