plotting y and log(y) in one figure
[This article was first published on Wiekvoet, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
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.Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
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)))
To leave a comment for the author, please follow the link and comment on their blog: Wiekvoet.
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.