rstudio / leaflet

R Interface to Leaflet Maps
http://rstudio.github.io/leaflet/
Other
807 stars 508 forks source link

(log) transforming color palettes #665

Open HughSt opened 4 years ago

HughSt commented 4 years ago

Hi - I'm just wondering whether it is (or could be) possible to apply a transformation when using the colorNumeric function. I'd like to be able to map a continuous outcome, but log transformed. Obviously I can just log transform the values before creating the colorNumeric function, but when I come to addLegend, I want it to display the actual (non-transformed) values using a log scaled ramp. e.g. if I were plotting a raster with values that go from 1:1000 I want the legend ticks to be equally spaced at 1, 10, 100 and 1000.

Thanks for a great package!

jhelvy commented 3 years ago

Second this.

For now, my work-around is to use discrete bins (which isn't ideal for a continuous variable). For example, here is how I made a square root transformation for values between 0 and 40 with 8 bins:

pal <- colorBin(
  palette = "YlOrRd",
  bins = round(seq(0, sqrt(40), length.out = 8)^2, 1), 
  domain = df$value)
mmyrte commented 3 years ago

Actually, it would seem that this is quite possible using labelFormat, just not super convenient - here's an example using a stars object and base 10 log/exp. (I resort to leafem for the handling of the stars-to-base64 conversion).

pal <- leaflet::colorNumeric(
  colormap,
  domain = NULL,
  na.color = "#00000000",
  alpha = TRUE
)

leaflet::leaflet() %>%
  leafem::addStarsImage(log10(stars), colors = pal) %>%
  leaflet::addLegend(
    pal = pal, values = log10(stars[[1]]),
    labFormat = leaflet::labelFormat(
      transform = function(x) 10^x
    )
  )

Edited to add: Of course, the breaks won't be very pretty this way, but if you were going for those, the colorBin approach is probably better anyways.

mtennekes commented 1 year ago

@tomroh Do you know if it is possible to have a continuous legend in leaflet with custom (in this case logarithmic) labels? The labFormat argument does not seem to work.

tomroh commented 1 year ago

I think this closest you can get is something like:

library(leaflet)
library(leaflegend)
data(quakes)
quakes1000 <- quakes[1:1000, ]
quakes1000[['x']] <- 1:1000
numPal <- colorNumeric('viridis', c(.01, 1000))
leaflet(quakes1000) %>%
  addTiles() %>%
  addCircleMarkers(color = ~numPal(x)) %>%
  addLegendNumeric(
    pal = numPal,
    values = ~x,
    position = 'topright',
    orientation = 'vertical',
    shape = 'stadium',
    height = 129,
    width = 18,
    bins = 5,
    fillOpacity = .5,
    numberFormat = function(x) {
      prettyNum(log10(x), format = "f", big.mark = ",", digits =
          3, scientific = FALSE)
    }
  )

Getting the breaks exactly can be tricky as pretty is always doing the binning.

tomroh commented 1 year ago

Or the inverse:

library(leaflet)
library(leaflegend)
data(quakes)
quakes1000 <- quakes[1:1000, ]
quakes1000[['x']] <- 1:1000
numPal <- colorNumeric('viridis', log10(quakes1000$depth))
leaflet(quakes1000) %>%
  addTiles() %>%
  addCircleMarkers(color = ~numPal(log10(depth))) %>%
  addLegendNumeric(
    pal = numPal,
    values = ~log10(depth),
    position = 'topright',
    orientation = 'vertical',
    shape = 'stadium',
    height = 129,
    width = 18,
    bins = 5,
    fillOpacity = .5,
    numberFormat = function(x) {
      prettyNum(x^10, format = "f", big.mark = ",", digits =
          3, scientific = FALSE)
    }