3

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)
6
  • You should include a minimal example of your data. Commented Nov 11, 2017 at 7:02
  • @Cedric, sorry for that. Now, I have added an example data. Commented Nov 11, 2017 at 7:12
  • Since I've tried on my own, I have edited your post and added an example. Commented Nov 11, 2017 at 9:08
  • In situations like this, I usually bin the continuous variable and then facet_grid() by the bin. It creates the same visual effect. Commented Nov 12, 2017 at 5:41
  • @CurtF. thanks for the suggestion, can you explain it a bit more Commented Nov 12, 2017 at 16:37

2 Answers 2

2

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

Sign up to request clarification or add additional context in comments.

1 Comment

that is perfect. Thank you for explaining!
2

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

2 Comments

Thanks for the answer. This solution is concise and beautiful. Is it possible to remove the label of FALSE and TRUE?
Adding + theme(strip.text.y = element_blank()) to the ggplot() chain should remove them entirely. Other options are possible too depending on exactly what you want.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.