menenuh
menenuh

Reputation: 15

How to specify distance between ticks in x & y axis?

I want to create a plot with custom axis tick spacing. What I want to achieve is similar to this plot: enter image description here

I can specify axis tick locations using breaks argument, but I can't change the distance between them.

dat <- data.frame(x = runif(100), y = runif(100))
ggplot(dat, aes(x,y)) + geom_point() + scale_x_continuous(breaks=c(0,0.1,0.2,0.4,0.8,1)) + scale_y_continuous(breaks=c(0,0.1,0.2,0.4,0.8,1))

enter image description here

What I essentially want is to focus on a specific interval (say 0:0.2) and have bigger spacing for this interval and squish the rest (0.2:1). Right now I do that by creating two graphs for my desired intervals, and glue them together with grid.arrange, but I was wondering if there was a solution that enables me to generate the plot in one go.

This is my current solution:

q1<-ggplot(dat, aes(x,y)) + geom_point() + ylim(c(0.2,1)) + xlim(c(0,0.2))+ theme(axis.text.x = element_blank(), axis.title.x = element_blank(), axis.ticks.x=element_blank())
q2<-ggplot(dat, aes(x,y)) + geom_point() + ylim(c(0.2,1)) + xlim(c(0.2,1))+ theme(axis.text = element_blank(), axis.title = element_blank(), axis.ticks=element_blank())
q3<-ggplot(dat, aes(x,y)) + geom_point() + ylim(c(0,0.2)) + xlim(c(0,0.2))
q4<-ggplot(dat, aes(x,y)) + geom_point() + ylim(c(0.2,1)) + xlim(c(0.2,1))+ theme(axis.text.y = element_blank(), axis.title.y = element_blank(), axis.ticks.y=element_blank())

grid.arrange(q1,q2,q3,q4)

enter image description here

Upvotes: 0

Views: 1589

Answers (2)

barboulotte
barboulotte

Reputation: 405

dat <- data.frame(x = runif(100), y = runif(100))
ggplot(dat, aes(x,y)) + 
  geom_point() + 
  scale_x_continuous(breaks=c(0,0.1,0.2,0.4,0.8,1)) + 
  scale_y_continuous(breaks=c(0,0.1,0.2,0.4,0.8,1))

enter image description here

dat$condx <- ifelse(dat$x > 0.2, "x2", "x1")
dat$condy <- ifelse(dat$y > 0.2, "y1", "y2")
dat$condxy <- paste(dat$condx, dat$condy)
ggplot(dat, aes(x, y, group=condxy)) + 
  geom_point() + 
  scale_x_continuous(breaks=c(0,0.05,0.1,0.15,0.2,0.4,0.6,0.8,1)) + 
  scale_y_continuous(breaks=c(0,0.05,0.1,0.15,0.2,0.4,0.6,0.8,1)) +
  facet_grid(condy~condx, scales="free")

enter image description here

(Related to Two scales in the same axis)

Regards,

Upvotes: 0

teunbrand
teunbrand

Reputation: 38063

Ok first I'll have to make the obligatory comment that squishing part of the data in a way that disconnects the position on the plot from a direct connection to the data is not a good idea in general.

That said, here is how you can do it. We can make a function factory that produces a transformation object with the scales factor. The function factory accepts a range it should squish and a factor by how much to squish the data. I haven't tested it exhaustively, but I think it works correctly.

library(ggplot2)
library(scales)

squish_trans <- function(range, factor = 10) {
  force(range)
  force(factor)
  forward <- function(x) {
    test_between <- x > range[1] & x < range[2]
    test_over <- x >= range[2]
    between <- ((x - range[1]) / factor) + range[1]
    over <- (x - range[2] + diff(range) / factor) + range[1]
    ifelse(test_over, over,
           ifelse(test_between, between, x))
  }
  reverse <- function(x) {
    test_between <- x > range[1] & x < range[1] + diff(range) / factor
    test_over <- x >= range[1] + diff(range) / factor
    between <- ((x - range[1]) * factor) + range[1]
    over <- (x - range[1]) - diff(range) / factor + range[2]
    ifelse(test_over, over,
           ifelse(test_between, between, x))
  }
  trans_new(
    "squish_trans",
    transform = forward,
    inverse = reverse
  )
}

Now we simply run the function factory as trans argument with the range you want to squish. You can notice that the 0.2-1 range (80% of data range) is now 0.08/0.28 ~= 0.28 (~28%) of the axis range because we squish with a factor 10.

dat <- data.frame(x = runif(100), y = runif(100))

ggplot(dat, aes(x,y)) + geom_point() + 
  scale_x_continuous(breaks=c(0,0.1,0.2,0.4,0.8,1),
                     trans = squish_trans(c(0.2, Inf))) + 
  scale_y_continuous(breaks=c(0,0.1,0.2,0.4,0.8,1),
                     trans = squish_trans(c(0.2, Inf)))

Created on 2021-02-05 by the reprex package (v1.0.0)

Upvotes: 1

Related Questions