Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Log-shift transformation does not squish the data

When I plot a density using geom_spatraster, there's a particularly prominent peak that's 'bright' in the visualization. This spike skews the color scale, compressing the representation of other data points to such an extent that the underlying structure becomes obscured. A standard log transformation doesn't resolve this. My expectation is that a log-shift transformation should compress the data even further. Therefore, I suspect there's something I'm misunderstanding. The following is a minimum working example, using the x-axis to illustrate the issue instead of the 'fill' aesthetic:

library(ggplot2)
library(scales)

# Using mtcars dataset
mtcars[1,"disp"] <- 1500

my_transform <- function(x) log(x + 10)
my_inverse <- function(x) exp(x) - 10

my_trans <-  scales::trans_new("yes_mate", transform = my_transform, inverse = my_inverse)

ggplot(mtcars, aes(x = disp, y = 1,
                   color = disp
                   )) +
  geom_point(size = 5) +
  scale_x_continuous(
    trans = my_trans,
    limits = c(100,1500),
    breaks = c(100, 500, 1000, 1500)) 

So here I would expect the data points to shift further together, but the contrary is the case:

my_transform <- function(x) log(x + 10000)
my_inverse <- function(x) exp(x) - 10000

my_trans <-  scales::trans_new("yes_mate", transform = my_transform, inverse = my_inverse)

ggplot(mtcars, aes(x = disp, y = 1,
                   color = disp
                   )) +
  geom_point(size = 5) +
  scale_x_continuous(
    trans = my_trans,
    limits = c(100,1500),
    breaks = c(100, 500, 1000, 1500)) 
like image 299
KeepDigging Avatar asked Apr 16 '26 09:04

KeepDigging


2 Answers

Adding bigger and bigger offsets will bring the values closer together in the absolute scale, but if you similarly scale your axis then counterintuitively the lower values will be bunched together more the larger you make the offset.

x <- c(100, 150, 200, 250, 1500)

par(mfrow=c(1,3), mar=rep(2, 4))
lapply(1:3, \(e) plot(log(x+10^e), x, ann=FALSE))

increasing offsets bunch lower values closer together

The solution isn't so much the offset -- the smaller the better but that'll only get you so far. What you want is a log-log(-log? -log?) transform:

## Stack those logs! (more works too)
my_transform <- function(x) log(log(x + 1E-3))
my_inverse <- function(x) exp(exp(x)) - 1E-3

my_trans <-  scales::trans_new("yes_mate", transform = my_transform, inverse = my_inverse)

ggplot(mtcars, aes(x = disp, y = 1, color = disp)) +
  geom_point(size = 5) +
  scale_x_continuous(
    trans = my_trans,
    limits=c(100, 1500),
    breaks = c(100, 500, 1000, 1500)
  )

log-log brings all values closer together

like image 98
PBulls Avatar answered Apr 19 '26 01:04

PBulls


Could you use transformed color/fill scale? Instead of scale_color_continuous() use

continuous_scale(
    aesthetics = "color", 
    palette = pal_seq_gradient(
      low = "#132B43", 
      high = "#56B1F7",  
      "Lab"),
    transform = "log"
  ) +
  guides(color = "colorbar")
like image 29
Michiel Duvekot Avatar answered Apr 18 '26 23:04

Michiel Duvekot



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!