r-spatial / mapview

Interactive viewing of spatial data in R
https://r-spatial.github.io/mapview/
GNU General Public License v3.0
515 stars 91 forks source link

Option to plot a single legend for a stacked raster plot #44

Open adrfantini opened 7 years ago

adrfantini commented 7 years ago

Consider this plot:

mapview(stack(poppendorf[[1]], poppendorf[[1]]+0.01), legend=TRUE)

It's easy to see that the legend is duplicated for no reason. This is ugly and wastes space for those plots where the same data could share a legend (say, e.g., a stack of rasters with mean precipitation for different years). A simple solutions could be this something like:

mapview(poppendorf[[1]], legend=TRUE) + mapview(poppendorf[[1]]+0.01)

But this does not work either: the colors are of course different because the input data is different.

How can have mapview share layer legends with a single call? Or how can I overlay correctly different mapview items while inheriting the same legend?

tim-salabim commented 7 years ago

What you are describing is not entirely correct. If you add 10000 instead of 0.01

mapview(stack(poppendorf[[1]], poppendorf[[1]] + 10000), legend = TRUE)

you will see that the legends are not duplicated. They are, as they should be, reflecting the range of the raster layers. I don't quite understand your 'simple solution' as it is exactly the same as the first example only that we omit the second legend. The colors of the images are still identical as they have the same relative distribution of values between their min and max values, regardless of what you add:

mapview(poppendorf[[1]], legend=TRUE) + mapview(poppendorf[[1]] + 10000)

I understand your desire to have only one legend that fits all images of a stack and I guess it makes sense to provide the user with that option. I will need to think carefully about a way to implement this though, so it likely won't happen for some time (but feel free to contribute ;-) ).

The reason we haven't implemented this is that in mapview we aim to have generalised methods that work regardless of the input data. Streching the legend to cover the complete range of the stack may make sense in many cases (including the example you mention of precipitation over the years) yet it is not a feasible general solution. If you have extreme layers, e.g. one layer with only small values and another with only large values you won't see any patterns in either of them.

For us, a more pressing solution is to be able to link legends to layers so that only active layer legends are shown.

adrfantini commented 7 years ago

I added 0.01 as a simple way to differentiate the two rasters without changing the data much, so that a single legend would comfortably fit both. Of course visually it's impossible to tell.

The "simple solution" indeed is not a solution because if I had used two rasters with different data, then the distribution of values would be different and the legend would not be able to represent both plots.

Maybe adding a flag for a "common" legend for stretching the range to cover all layers would be the simplest approach, keeping the default as it is.

Andreas-Bio commented 5 years ago

I tried to reproduce the example because I am interested in this too and it fails.

mapview(stack(poppendorf[[1]], poppendorf[[1]]+0.01), legend=TRUE)
Error in if (drop) { : argument is not interpretable as logical
frasemcl commented 1 week ago

+1 for the proposed enhancement, I'm trying to do the same thing as the OP. Thanks for the useful package!