2

I want to recreate an "image" plot in ggplot (because of some other aspects of the package). However, I'm facing a problem caused by my y-scale, which is defined by unequally but logically spaced values, e.g. I would have z values for y = 2,4,8,16,32. This causes the tiles to not be equally large, so I have these white bands in my figure. I can solve this by transforming the y values in a factor, but I don't want to do this because I'm also trying to plot other geom objects on the figure which require a numeric scale. This clearifies my problem a bit:

# random data, with y scale numeric
d <- data.frame(Var1=rep(1901:2000,10),Var2=rep(c(2,4,8,16,32),each=100),value=rnorm(500,50,5))
line=data.frame(Var1=1901:2000,Var2=rnorm(50,1.5,0.5))
ggplot(d, aes(x=Var1, y=Var2)) +
  geom_tile(aes(fill=value)) +
  geom_line(data=line)

 # y as factor
d2 = d
d2$Var2=as.factor(d2$Var2)    ggplot(d2, aes(x=Var1, y=Var2)) +
  geom_tile(aes(fill=value)) +
  geom_line(data=line)

I tried attributing the line values to the value of the nearest factor level, but this introduces a big error. Also, I tried the size option in geom_tile, but this didn't work out either.

In the example the y data is log transformed, but this is just for the ease of making a fake dataset.

Thank you.

Wave
  • 1,216
  • 1
  • 9
  • 22
  • What's "line" in `data=line` here? You've not defined it, and ggplot is complaining about trying to deal with the builtin "line" **function** – Spacedman Oct 06 '14 at 09:42
  • sorry, I forgot to copy the line. It's changed now. – Wave Oct 06 '14 at 09:45
  • Try the setting `height` aesthetic to the difference in Y coords. There's a bit of fiddling needed because the tiles are centred at the Y coords, but should be easy enough. – Spacedman Oct 06 '14 at 09:52
  • If I do that the white bands do indeed dissapear, but the cells do not have the same size. – Wave Oct 06 '14 at 09:56
  • How can you have the bands with the same height but keep the numeric scale so the line plot is possible? Unless there's a simple transformation but you seem to want it general. Can you include or point us to an image of what you want? – Spacedman Oct 06 '14 at 09:59
  • Ok, to make my question easier (and because I now that originally I asked something that is from a mathematical point of view wrong, but just served to interpret my data easier) I changed it so my y values are now 2^X, which will do as well. I can't seem to find an example though, sorry. – Wave Oct 06 '14 at 12:05

2 Answers2

1

Something like this??

ggplot(d, aes(x=Var1, y=Var2)) +
  geom_tile(aes(fill=value)) +
  geom_line(data=line)+
  scale_y_continuous(trans="log2")

Note the addition of scale_y_continuous(trans="log2")

EDIT Based on OP's comment below.

There is no built-in "reverse log2 transform", but it is possible to create new transformations using the trans_new(...) function in package scales. And, naturally, someone has already thought of this: ggplot2 reverse log coordinate transform. The code below is based on the link.

library(scales)
reverselog2_trans <- function(base = 2) { 
  trans <- function(x) -log(x, base) 
  inv <- function(x) base^(-x) 
  trans_new(paste0("reverselog-", format(base)), trans, inv, log_breaks(base = base), domain = c(1e-100, Inf))
} 
ggplot(d, aes(x=Var1, y=Var2)) +
  geom_tile(aes(fill=value)) +
  geom_line(data=line)+
  scale_y_continuous(trans="reverselog2") 

jlhoward
  • 58,004
  • 7
  • 97
  • 140
  • Thanks, that works fine on the example, but in my more complicated graph I use scale_y_reverse, and I can't use both. How do I use both? The error is: formal argument "trans" matched by multiple actual arguments – Wave Oct 06 '14 at 14:23
  • 1
    Sorry, found it, thanks to this link: http://stackoverflow.com/questions/11053899/how-to-get-a-reversed-log10-scale-in-ggplot2. library(scales) reverselog2_trans <- function(base = exp(1)) { trans <- function(x) -log(x, base) inv <- function(x) base^(-x) trans_new(paste0("reverselog-", format(base)), trans, inv, log_breaks(base = base), domain = c(1e-100, Inf)) } – Wave Oct 06 '14 at 14:46
  • Close, but for a `reverselog2_trans(...)` the default `base` should be `2`, not `e`. I'll add this to the answer for others' benefit. – jlhoward Oct 06 '14 at 14:55
0

Perhaps another approach using a discrete scale and facets might be a possibility:

 d <- data.frame(Var1=rep(1901:2000,10),Var2=rep(c(2,4,8,16,32),each=100),value=rnorm(500,50,5), chart="tile" )
 d$Var2 <- factor(d$Var2, levels=rev(unique(d$Var2)))
 line <- data.frame(Var1=1901:2000,Var2=rnorm(50,1.5,0.5), chart="line")
 ggplot(d, aes(x=Var1, y=Var2)) +
   geom_tile(aes(y = Var2, fill=value) ) +
   geom_line( data=line ) +
   scale_y_discrete() +  
   facet_grid( chart ~ ., scale = "free_y", space="free_y")

which gives a chart like:enter image description here

WaltS
  • 5,410
  • 2
  • 18
  • 24