1

Is there a possible way to shade an area between two lines using Base R given these two constraints:

  • I can't use ggplot2 because other parts of my app will not work (a Shiny clickId limitation; more specifically, using ggplot2's clickId does not give the real x and y values of the data).
  • I also can't use polygon because NAs are present in my data, which makes the "shade" created by polygonclose prematurely.

Here is a SSCCE (excluding the Shiny components):

#my sample data
vals_time <- c(1:10)
vals_line1 <- c(8, 9, NA, NA, 7, 8, 7, NA, 9, 4)
vals_line2 <- c(4, 5, NA, NA, 6, 10, 8, NA, 5, 2)

#create line graphs without the shade
plot(x = vals_time, y = vals_line1, type = "l", ylim = c(0,11))
lines(x= vals_time, y = vals_line2)

Here's how I used the polygon function:

polygon(x = c(vals_time, vals_time[10:1]),
        y = c(vals_line1, vals_line2[10:1]),
        col = rgb(1, 0, 0, 0.5))
Henrik
  • 65,555
  • 14
  • 143
  • 159
sober
  • 121
  • 1
  • 7
  • I'm currently thinking of an excruciating workaround to this: find the consecutive sets of x with no NAs and do a polygon "shade" for each complete set. But before I dive into this, is there an easier way? – sober Apr 20 '15 at 06:30
  • 1
    Please provide a **minimal, self contained example**. Check these links for general ideas, and how to do it in R: [**here**](http://stackoverflow.com/help/mcve), [**here**](http://www.sscce.org/), [**here**](http://adv-r.had.co.nz/Reproducibility.html), and [**here**](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example/5963610#5963610). – Henrik Apr 20 '15 at 06:38

1 Answers1

2

You can split your data by the na values and then use polygon on the splitted data. I would first create a data.frame. Then you can split the data.frame on NA and use na.omit to leave out NA values. Finally use lapply and polygon to plot the data.

df <- data.frame(time = vals_time, 
                 l1 = vals_line1, 
                 l2 = vals_line2)
plot(x = df$time, y = df$l1, type = "l", ylim = c(0, 11))
lines(x = df$time, y = df$l2)
lst <- lapply(split(df, cumsum(is.na(df$l1))), na.omit)
lapply(lst, function(d) 
  polygon(x = c(d$time, rev(d$time)), y = c(d$l1, rev(d$l2)), col = rgb(1,0,0,0.5)))
shadow
  • 21,823
  • 4
  • 63
  • 77