plotting y and log(y) in one figure

December 15, 2013
By

Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Sometimes I have the desire to plot both on the linear and on the log scale. To save space just two figures is not my solution. I want to reuse the x-axis, legend, title. This post examines possibilities to do so with standard plot tools, lattice and ggplot2.

Data

Data is completely artificial.
library(ggplot2)
library(lattice)

datastart <- data.frame(x=rep(1:5,2),
y=c(1,2,10,50,1, .1,9,8,20,19),
type=rep(c(‘a’,’b’),each=5))
datastart

x    y type
1  1  1.0    a
2  2  2.0    a
3  3 10.0    a
4  4 50.0    a
5  5  1.0    a
6  1  0.1    b
7  2  9.0    b
8  3  8.0    b
9  4 20.0    b
10 5 19.0    b

standard plot tools

The trick here is to make two plots. The top plot has no x-axis, the bottom one no title. To make the two plot surfaces equal in size the room reserved for x-axis and title is the same.
par(mfrow=c(2,1),mar=c(0,4.1,4,2))
plot(y~x,
data=datastart,
axes=FALSE,
frame.plot=TRUE,
xlab=”,
main=’bla bla’,
col=c(‘red’,’green’)[datastart\$type])
legend(x=’topleft’,
legend=c(‘a’,’b’),
col=c(‘red’,’green’),
pch=1)
axis(side=2,las=1)
par(mar=c(4,4.1,0,2))
plot(y~x,
data=datastart,
axes=FALSE,
frame.plot=TRUE,
xlab=’x’,
log=’y’,
ylab=’log(y)’,
col=c(‘red’,’green’)[datastart\$type]
)
axis(side=2,las=1)
axis(side=1)

lattice

As far as I understand, lattice does not have the tools to fiddle this extreme with axis. The trick then is to add a copy of the data on logarithmic scale and manually control the labels. Lattice does not understand that the x-axis are same, but some suppression is possible.
data1=datastart
data2=datastart
data1\$lab=’linear’
data2\$lab=’log’
data2\$y <- log10(data2\$y)
dataplot <- rbind(data1,data2)

at2 <- axisTicks(range(data2\$y),log=TRUE,nint=4)
at1 <- axisTicks(range(data1\$y),log=FALSE,nint=5)
atx <- axisTicks(range(data1\$x),log=FALSE,nint=5)
dataplot\$lab <- factor(dataplot\$lab,levels=c(‘linear’,’log’))
xyplot(y  ~ x | lab,groups=type,data=dataplot,layout=c(1,2),
main=’bla bla’,
as.table=TRUE,
auto.key=TRUE,
scales=list(relation=’free’,
x=list(at=list(NULL,atx)),
y=list(at=list(at1,log10(at2)),
labels=list(format(at1),format(at2))
)
))

ggplot2

The trick here is that ggplot2 can have a free y-axis, but you cannot set the labels per axis. Instead it is a common y-axis which has adapted labels. ggplot chooses the range for the y-axis itself, you have to make sure that the labels you feed it match that range. To make that fit in the end I just shifted the whole log part to a different range. Some of the code of lattice is re-used.
dataplot2 <- dataplot
offset <- -10
breaks=c(-11,-10,-9)
dataplot2\$y[dataplot2\$lab==’log’] <- dataplot2\$y[dataplot2\$lab==’log’] +offset
p <- ggplot(dataplot2, aes(x, y,colour=type)) + geom_point()
p + facet_grid(lab ~ .,
scales=’free_y’) +
labs(title = ‘bla bla’) +
scale_y_continuous(
breaks = c(breaks,at1),
labels=c(format(10^(breaks-offset)),format(at1)))

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.