9

I'm trying to do a levelplot using ggplot2 for a (meteorological) variable. The variable is measured continuously in time (my x-axis), but in non-continuous heights (y-axis) at every time step. The produced plot therefore shows data at the heights (y-coordinates) specified, but nothing in between. Here's an example:

library(ggplot2)
data <- runif(400, min=0, max=10)
index <- c(1:20)
heights <- c(1,2,3,4,5,7,9,12,15,19,23,28,33,39,45,52,59,67,75,83)
dat <-     as.data.frame(cbind(expand.grid(X=index,Y=heights),data))                        
ggplot(dat, aes(x=dat[,1], y=dat[,2],z=dat[,3])) +geom_tile(aes(fill=dat[,3]))

This produces the following plot: image here

Is there an easy way to fill the plot fully, i.e. make the lines in the upper part of the plot broader? Thank you!

Cornelius
  • 93
  • 5
  • `geom_tile` takes a `height` aesthetic that you can use. I would advise to not use `dat[,1]` to refer to data using `ggplot`, use variable names instead. – Axeman Feb 06 '18 at 10:06
  • 1
    I would suggest looking at this [great answer](https://stackoverflow.com/a/48580629/1286528) about extrapolating missing values when plotting something similar – pogibas Feb 06 '18 at 10:14
  • @Axeman, could you please elaborate about the height argument? I assume it would be some kind of vector specifying heights for every line in the plot? – Cornelius Feb 06 '18 at 10:34
  • @PoGibas, thank you for that link. I was trying to avoid having to interpolate my data for laziness reasons, but it might be the way I have to go. – Cornelius Feb 06 '18 at 10:35

3 Answers3

4

You can use the height and width attributes in geom_tile, alternatively geom_rect

library(tidyverse)
data <- runif(400, min=0, max=10)
index <- c(1:20)
heights <- c(1,2,3,4,5,7,9,12,15,19,23,28,33,39,45,52,59,67,75,83)

dat <- crossing(index = index, heights = heights) %>% 
  mutate(
    Z = data,
    index0 = index - 1) %>% 
  left_join(data_frame(heights, heights0 = c(0, heights[-length(heights)])))    

ggplot(dat, aes(xmin = index0, xmax = index, ymin = heights0, ymax = heights, fill = Z)) +
  geom_rect()

This assumes that your heights are the top of each level and that they start at zero.

enter image description here

loki
  • 9,816
  • 7
  • 56
  • 82
Richard Telford
  • 9,558
  • 6
  • 38
  • 51
  • I like this one, but alas, the height information I have in my real data marks the center of the grid points. – Cornelius Feb 06 '18 at 11:24
4

OK one more solution.. you could interpolate using the approx function. Although maybe 2D kriging would be more appropriate for your application???

library(purrr)
dat2<- dat %>%
  split(.$X) %>%
  map_dfr(~ approx(.$Y, .$data, xout =1:83), .id = "X") 

ggplot(dat2, aes(x=as.integer(dat2$X), y=dat2$x, z=dat2$y)) +geom_tile(aes(fill=dat2$y))

That will give you : enter image description here

Stephen Henderson
  • 6,340
  • 3
  • 27
  • 33
1

You could convert the y axis to be factor in order to eliminate the dead space. This will, however, not make the upper lines broader.

ggplot(dat, aes(x=dat[,1], y=factor(dat[,2]),z=dat[,3])) +geom_tile(aes(fill=dat[,3]))

enter image description here

loki
  • 9,816
  • 7
  • 56
  • 82
  • Thank you, but I would really like to retain the spatial information that I have in my heights. – Cornelius Feb 06 '18 at 10:36
  • Then, I think you need to fill the empty lines with the upper or lower information. I am working on that. brb with an edit – loki Feb 06 '18 at 10:37