Logarithmic grid for plot with 'ggplot2'

pravi picture pravi · Feb 25, 2015 · Viewed 10.3k times · Source

I am trying to create a plot with logarithmically spaced grids using ggplot2 just like in the below figure. I get equidistant grids, but not log spaced ones. I know I am missing some parameter which I don't seem to get as of now. I have seen a lot of questions on the topic like Pretty ticks for log normal scale using ggplot2 (dynamic not manual), but do not solve the problem I am looking for.

set.seed(5)
x <- rlnorm(1000, meanlog=3.5, sdlog=1)
y <- rlnorm(1000, meanlog=4.0, sdlog=1)
d <- data.frame(x, y)

plot(x, y, log="xy", las=1)
grid(nx=NULL, ny=NULL, col= "blue", lty="dotted", equilogs=FALSE)
library(magicaxis)
magaxis(side=1:2, ratio=0.5, unlog=FALSE, labels=FALSE)

enter image description here

library(ggplot2)
library(MASS)
library(scales)
a <- ggplot(d, aes(x=x, y=y)) + geom_point() +
     scale_x_log10(limits = c(1, NA), 
                   labels = trans_format("log10", math_format(10^.x)),
                   breaks=trans_breaks("log10", function(x) 10^x, n=4)) +
     scale_y_log10(limits = c(1, NA),
                   labels = trans_format("log10", math_format(10^.x)),
                   breaks=trans_breaks("log10", function(x) 10^x, n=4)) +
     theme_bw() + theme(panel.grid.minor = element_line(color="blue", linetype="dotted"), panel.grid.major = element_line(color="blue", linetype="dotted"))
a + annotation_logticks(base = 10)

enter image description here

Answer

Ian Kent picture Ian Kent · Sep 18, 2017

To build on Gabor's answer, it is unnecessary to define the ticks only in the exact range of the plot. You can instead define breaks for a large range of values that will cover pretty much everything you'd ever expect to see and use those to create nice grid lines for any plot. While perhaps not the most elegant solution, it's easy and more generalizable than having to manually figure out ranges every time.

breaks <- 10^(-10:10)
minor_breaks <- rep(1:9, 21)*(10^rep(-10:10, each=9))

d %>% 
    ggplot(aes(x, y)) +
        geom_point() +
        scale_x_log10(breaks = breaks, minor_breaks = minor_breaks) +
        scale_y_log10(breaks = breaks, minor_breaks = minor_breaks) +
        annotation_logticks() +
        coord_equal() +
        theme_bw()

Link to image of plot