Cat
Cat

Reputation: 1

Change x-axis scale to cuberoot without transforming raw data using trans_new()

I need to change the x-axis of my ggplot figure to a cuberoot scale, without transforming the raw data. My code below had been working but with the new R update, I am getting the error,

Error in if (zero_range(as.numeric(transformation$transform(limits)))) { : missing value where TRUE/FALSE needed

I'm wondering if anyone knows why this error is occurring now and/or solutions/workarounds to plot my figure on the cuberoot scale. Thanks!

First few lines of data:

structure(list(site = c("US", "US", "US", "US", "US", "US"), 
    Transect = c(1L, 1L, 1L, 1L, 1L, 1L), Plot = c(100L, 103L, 
    106L, 109L, 112L, 115L), Year = c(2020L, 2020L, 2020L, 2020L, 
    2020L, 2020L), SYear = c("2020-2021", "2020-2021", "2020-2021", 
    "2020-2021", "2020-2021", "2020-2021"), E.Delta = c(-0.0380000000000109, 
    -0.0930000000000746, -0.0950000000000273, -0.0709999999999127, 
    -0.104000000000042, -0.0989999999999327), I = c(1, 1, 1, 
    1, 1, 1), AllRtedPctCov = c(0, 0, 0, 0, 0, 0), NoRtedVeg = c(1, 
    1, 1, 1, 1, 1), PerCov.15 = structure(c(1L, 1L, 1L, 1L, 1L, 
    1L), levels = c("0", "1"), class = "factor")), row.names = c(NA, 
6L), class = "data.frame")

**My code: **

transform_cuberoot = function(){
  trans_new('cuberoot',
            transform = function(x) x^(1/3),
            inverse = function(x) x^3,
            breaks = c(0, 0.01, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0),
            domain = c(-Inf, Inf))
} 

 
ggplot(df, aes(x = I, y = E.Delta, color = PerCov.15)) +
  geom_point(size = 1.5) +
  facet_wrap(~site + SYear, scales = "free") +
  theme_classic() +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  labs(x = "Inundation-Duration", y = "Change in Elevation", color =" Percent Rooted Cover") +
  scale_colour_brewer(labels= c("<15%", ">15%"), type = "qual", palette = 3) + # qual 3 or seq 1
  theme(axis.title.x = element_text(size = 16, vjust = -2),
        axis.title.y = element_text(size = 16, vjust = 5),
        legend.title = element_text(size = 16),
        legend.text = element_text(size = 16),
        strip.background = element_blank(),
        strip.text = element_text(size = 18),
        axis.text = element_text(size = 14),
        plot.margin = unit(c(2,2,2,2), "cm"),
        panel.spacing = unit(3, "lines"))+
  scale_x_continuous(trans = transform_cuberoot(), breaks = c(0, 0.01, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0),labels=c(0, 0.01, 0.1, " ", 0.3, " ", " ", 0.6, " ", " ", " ", 1.0)) 

I have also tried using the workaround,

coord_trans(x = transform_cuberoot())

instead of of the trans = transform_cuberoot() argument in scale_x_continuous. This works but removes other important plotting features such as the dashed line at y = 0 and the y-axis line. It also produces 18 warnings of:

In transform(..., self = self) : Transformation introduced infinite values in x-axis

See below for an example of the figure I'm looking for versus what I'm able to produce with the workaround.

What I want/trying to re-create (with a horizontal line at 0 and wrapped for each site):

What I currently have with the workaround:

Upvotes: 0

Views: 68

Answers (1)

stefan
stefan

Reputation: 125418

You can fix the issue by restricting the domain for your cuberoot transformation to non-negative values, i.e. use domain=c(0, Inf).

Note: As already pointed out by @BenBolker the issue is not reproducible using your example data, so I altered it to include a zero value. After some experimenting the issue arises only when the variable mapped on x includes some small, nearly zero values. From this I would guess that this has to do with the (default) expansion of the scale and as a confirmation of my guess I tried with expand = c(0, 0) which also works fine even for a domain=c(-Inf, Inf).

library(ggplot2)
library(scales)

df$I <- c(0.0, 0.01, 0.1, 0.8, 0.9, 1.0)
transform_cuberoot <- function() {
  trans_new("cuberoot",
    transform = function(x) x^(1 / 3),
    inverse = function(x) x^3,
    domain = c(0, Inf)
  )
}

ggplot(df, aes(x = I, y = E.Delta, color = PerCov.15)) +
  geom_point(size = 1.5) +
  facet_wrap(~ site + SYear, scales = "free") +
  theme_classic() +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  labs(
    x = "Inundation-Duration", y = "Change in Elevation",
    color = " Percent Rooted Cover"
  ) +
  scale_colour_brewer(
    labels = c("<15%", ">15%"),
    type = "qual", palette = 3
  ) + # qual 3 or seq 1
  scale_x_continuous(
    transform = transform_cuberoot(),
    breaks = c(0, 0.01, 0.1, 0.3, 0.6, 1.0)
  )

Just as a reference, here I reproduce the issue using domain = c(-Inf, Inf):

transform_cuberoot <- function() {
  trans_new("cuberoot",
    transform = function(x) x^(1 / 3),
    inverse = function(x) x^3,
    domain = c(-Inf, Inf)
  )
}

ggplot(df, aes(x = I, y = E.Delta, color = PerCov.15)) +
  geom_point(size = 1.5) +
  facet_wrap(~ site + SYear, scales = "free") +
  theme_classic() +
  geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
  labs(
    x = "Inundation-Duration", y = "Change in Elevation",
    color = " Percent Rooted Cover"
  ) +
  scale_colour_brewer(
    labels = c("<15%", ">15%"),
    type = "qual", palette = 3
  ) + # qual 3 or seq 1
  scale_x_continuous(
    transform = transform_cuberoot(),
    breaks = c(0, 0.01, 0.1, 0.3, 0.6, 1.0)
  )
#> Error in if (zero_range(as.numeric(transformation$transform(limits)))) {: missing value where TRUE/FALSE needed

Upvotes: 2

Related Questions