How can I remove part of y-axis and reverse the axis in ggplot2

Viewed 1776

I have been trying to plot in ggplot2. On x-axis, I have factors. On y-axis, I have values that are either very small or very large, when I am plotting, in the middle part of the plot there is nothing. I want to squish this middle part but want to have y-axis in reverse order (100,90,80...0). I have searched and found out to squish the middle part by using a function borrowed from the Stackoverflow. The functions is:

squish_trans <- function(from, to, factor) { 

  trans <- function(x) {    
  # get indices for the relevant regions
  isq <- x > from & x < to
  ito <- x >= to

  # apply transformation
  x[isq] <- from + (x[isq] - from)/factor
  x[ito] <- from + (to - from)/factor + (x[ito] - to)

  return(x)
}

inv <- function(x) {

  # get indices for the relevant regions
  isq <- x > from & x < from + (to - from)/factor
  ito <- x >= from + (to - from)/factor

  # apply transformation
  x[isq] <- from + (x[isq] - from) * factor
  x[ito] <- to + (x[ito] - (from + (to - from)/factor))

  return(x)
}

# return the transformation
return(trans_new("squished", trans, inv))
}

This function work very well, however, I want to reverse the y-axis. Not able to do it. Please help. Data looks like this:

s<-
"Groups Mean Stdev
F 99 0.414048151
F 98 0.457120465
F 92 0
F 1 0.01
J 80 1.638558759
E 88 0.681379406
M 83 0.01
M 1 0.01"
S <- read.delim(textConnection(s),header=TRUE,sep=" ",strip.white=TRUE)
2 Answers

If you look into :

> scale_y_reverse
function (...) 
{
    scale_y_continuous(..., trans = reverse_trans())
}
<environment: namespace:ggplot2>
> reverse_trans
function () 
{
    trans_new("reverse", function(x) -x, function(x) -x, minor_breaks = regular_minor_breaks(reverse = TRUE))
}

You see that you just have to use -x for both transformation and its inverse

require(scales)    
squish_trans <- function(from, to, factor) { 

  trans <- function(x) {    
      # get indices for the relevant regions
      isq <- x > from & x < to
      ito <- x >= to

      # apply transformation
      x[isq] <- from + (x[isq] - from)/factor
      x[ito] <- from + (to - from)/factor + (x[ito] - to)

      return(-x)
  }

  inv <- function(x) {

      # get indices for the relevant regions
      isq <- x > from & x < from + (to - from)/factor
      ito <- x >= from + (to - from)/factor

      # apply transformation
      x[isq] <- from + (x[isq] - from) * factor
      x[ito] <- to + (x[ito] - (from + (to - from)/factor))

      return(-x)
  }

# return the transformation
  return(trans_new("squish_and_reverse", trans, inv))
}

ggplot(S,aes(x=Groups,y=Mean))+geom_point()+
    scale_y_continuous(trans = squish_trans(10, 80, 5))

enter image description here

I'd recommend just computing bins for the data and then using facet_grid() by bin. Here's an example:

# example data
df <- data.frame(group=rep(c('A', 'B', 'C', 'D'), 10), 
                 value=c(rnorm(10), rnorm(10)+100)
                 )

# compute bins (using tidyverse packages tidyr and dplyr)
df %>%
    mutate(bin = value > 50) %>%

# plot the data using a facet_grid with free y scales
    ggplot(aes(x=group, y=value)) +
        facet_grid(bin ~ ., scale='free_y') +
        geom_point() +
        scale_y_reverse()

# save plot
ggsave('SO_47234710.png', width=4, height=3)

It's essential to use scale='free_y' when using this approach so that the facets have separate y-scales.

Example of binning and then facet_grid

Related