Repository navigation
A function to add a colored polygon to a plot for confidence intervals #2
Description
The title says it all. The function, which I called ribbon() is a slight modification to polygon() with quality of life improvements to make it easier to add colored confidence intervals to a plot. Default values are taken for all polygon arguments, except for border, which is set to NA. Additionally, an alpha argument has been added to accommodate partially transparent confidence intervals. Any of the input values can be overwritten within this function's call.
A standard workflow would look something like this, which could not add in transparency.
data(cars)
# fit model
m1 <- lm(
dist ~ speed,
data = cars
)
# make predictions
preds <- predict(
m1,
newdata = data.frame(speed = 10:25),
interval = "confidence"
)
# base plot
blank(
xlim = c(10,25),
ylim = c(15,120),
xlab = "Speed",
ylab = "Stopping distance",
xaxt = "s",
yaxt = "s",
bty = "l",
las = 1
)
polygon(
x = c(10:25, rev(10:25)),
y = c(preds[,2], rev(preds[,3])),
col = "purple",
border = NA
)The function I am suggesting would replace polygon and in this case would look like:
ribbon(
x=10:25,
y=preds[,c("lwr","upr")],
col = "purple",
alpha = 0.5
)
In this case x does not need to be reversed (i.e., x = c(10:25, rev(10:25))) and you can input a two-column data.frame or matrix into y. Likewise, there is an alpha argument now which uses base R to set the alpha channel & make colors transparent if you want them to be. Code for this function is:
ribbon <- function(x, y, density=NULL, angle=45, border=NA,
col=NA, lty= par("lty"),...,fillOddEven=FALSE,
alpha = NULL
){
# error checks
if(!any(is.na(col)) & length(col)>1){
warning("Two values input to col. Only first element used.")
col <- col[1]
}
# check if y is a matrix
if(is.matrix(y)|is.data.frame(y)){
y <- c(y[,1], rev(y[,2]))
# check if x is half the length of y
if(length(y)/length(x) == 2){
x <- c(x, rev(x))
}
}
# evaluate color and alpha channel
if( is.na(col) ){
my_col <- NA
} else { # otherwise go through color process
#
if(
length(grep("^#", col)) == 1 & # if start with hash
nchar(col)>7 # & alpha channel is present
){
if(!is.null(alpha)){
warning("col already has alpha channel, ignoring alpha argument.")
my_col <- col
} else {
my_col <- col
}
} else {
# get rgb
my_rgbs <- col2rgb(col)
# set color
my_col <- rgb(
my_rgbs[1],my_rgbs[2],my_rgbs[3],max = 255,alpha = 255 * alpha
)
}
}
polygon(
x = x, y = y, density = density, angle = angle,
border = border, col = my_col, lty = lty,
fillOddEven = fillOddEven, ...
)
}Code, documentation, and tests are written. Happy to submit a PR if you want to check it out!
Activity
juniperlsimonis commentedon Jun 3, 2022
this was what you put in the PR right?
is there anything else in here that needs to be addressed still?
mfidino commentedon Jun 6, 2022
Yeah this should be in the PR I did (I just kept adding stuff on top of this) so it should be good to go!