Create automatically multiple rectangles between limit values - in ggplot R

Viewed 73

I would like to plot rectangles between specific values listed in a data frame, such as:

 Region <- c("A","B","A","B","A","C","B","C","A"),
  Lon <- c(31.03547, 37.25443, 65.97450, 69.90290, 101.77630,
                 105.32550, 148.86270, 147.72010, 146.10420)
  var1 <- rnorm(n = 9, mean = 15, sd = 100)
  regions <- data.frame(Region, Lon, var1)

This is an example where I show the region limits using geom_vline:

 ggplot(NULL)+
  geom_vline(data = regions, aes(xintercept=Lon, 
                                 linetype=region,
                                 color = region),
             size=0.6)+
  geom_point(data = regions, aes(x=Lon, y=var1, color=Region))+
  theme_bw()

I want to plot background rectangles that would be limited by those verticle lines.

I tried to look at this previous question: How to find the start and the end of sequences automatically in R for rectangles in ggplot However, it does not satisfy completely my needs, because I would like to plot rectangles for every region.

# Convert to runlength encoding
rle <- rle(regions$Region == "B")

# Determine starts and ends
starts <- {ends <- cumsum(rle$lengths)} - rle$lengths + 1

# Build a data.frame from the rle
dfrect <- data.frame(
  xmin = regions$Lon[starts],
  # We have to +1 the ends, because the linepieces end at the next datapoint
  # Though we should not index out-of-bounds, so we need to cap at the last end
  xmax = regions$Lon[pmin(ends + 1, max(ends))],
  fill = rle$values
)

ggplot(NULL)+
  geom_vline(data = regions, aes(xintercept=Lon, 
                                 linetype=region,
                                 color = region),
             size=0.6)+
  geom_rect(data = dfrect, 
            aes(xmin = xmin, xmax = xmax, ymin = -Inf, ymax = Inf,
                fill = fill), 
            alpha = 0.4) +
  geom_point(data = regions, aes(x=Lon, y=var1, color=Region))+
   theme_bw()

How can I define the rectangles for A and C too? consider that I have multiple regions, not only 3.

1 Answers

sample data

Region <- c("A","B","A","B","A","C","B","C","A")
Lon <- c(31.03547, 37.25443, 65.97450, 69.90290, 101.77630,
         105.32550, 148.86270, 147.72010, 146.10420)
var1 <- rnorm(n = 9, mean = 15, sd = 100)
regions <- data.frame(Region, Lon, var1)

code

library(data.table)
# Make regions a data.table
setDT(regions)
# first sort by lon, to avoind overlap in rectangles
setkey(regions, Lon)
# create boundaries of rectangles
regions[, Lon_end := data.table::shift(Lon, type = "lead", fill = Inf)][]
# plot
ggplot(data = regions) +
  geom_vline(aes(xintercept = Lon, linetype = Region, color = Region), size = 0.6) +
  geom_rect(mapping = aes(xmin = Lon, xmax = Lon_end, ymin = 0, ymax = 1, fill = Region), alpha = 0.1) 

output

enter image description here

Related