etienne etienne - 1 year ago 125
R Question

R - shade area between two crossing lines with different colors

I have a matrix (named ichimoku) with 516 rows and 2 columns ,each one of them containing values to be plotted, the goal is to recreate the clouds for the Ichimoku strategy.
Using matpot, I am able to plot these two curves but what I want is to shade the area between the two curves. I have two problems :

  • I tried using polygon to shade the area but it does not work. I suspect it is because the two series (senkouA and senkouB) cross several times on the plot instead of having one always greater than the other

  • I would like the area to be shaded in green if senkouA>senkouB and in red if senkouB>senkouA but from what I read the polygon can only be of one color.

Is there an other function that polygon which might help me achieve what I am looking for, that is a shade area in green between senkouA and senkouB when senkouA>senkouB and a shade area in red when senkouB>senkouA ?

The ichimoku matrix looks like this (the first column is senkouA, the other senkouB)

[,1] [,2]
[1,] 23323.62 23320.53
[2,] 23334.67 23328.71
[3,] 23334.11 23323.06
[4,] 23332.94 23323.06

here is my matplot function (which works):


and my polygon function (which doesn't):


Answer Source

If you find the intersections between the curves, then you can draw the polygons between the intersections. Here is a modification of a previous post where they find intersections between curves, and a function to draw the polygons.

## Some sample data
dat <- data.frame(x1=3*sin(3*(x=seq(0,10,len=100)))+rnorm(100),

intersects <- function(x1, x2) {
    seg1 <- which(!!diff(x1 > x2))                            # location of first point in crossing segments
    above <- x2[seg1] > x1[seg1]                              # which curve is above prior to crossing
    slope1 <- x1[seg1+1] - x1[seg1]
    slope2 <- x2[seg1+1] - x2[seg1]
    x <- seg1 + ((x2[seg1] - x1[seg1]) / (slope1 - slope2))
    y <- x1[seg1] + slope1*(x - seg1)
    data.frame(x=x, y=y, pindex=seg1, pabove=(1:2)[above+1L])  # pabove is greater curve prior to crossing

ichimoku <- function(data, addLines=TRUE) {
    ## Find points of intersections
    ints <- intersects(data[,1], data[,2])
    intervals <- findInterval(1:nrow(data), c(0, ints$x))

    ## Make plot
    matplot(data, type="n", col=2:3, lty=1, lwd=4)
    legend("topright", c("A", "B"), col=3:2, lty=1, lwd=2)

    ## Draw the polygons
    for (i in seq_along(table(intervals))) {
        xstart <- ifelse(i == 1, 0, ints$x[i-1])
        ystart <- ifelse(i == 1, dat[1,ints$pindex[1]], ints$y[i-1])
        xend <- ints$x[i]
        yend <- ints$y[i]
        x <- seq(nrow(data))[intervals == i]
        polygon(c(xstart, x, xend, rev(x)), c(ystart, data[x,1], yend, rev(data[x,2])),

    ## Add lines for curves
    if (addLines)
        invisible(lapply(1:2, function(x) lines(seq(nrow(data)), data[,x], col=x%%2+2, lwd=2)))

## Plot the data

enter image description here

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download