Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Line plot with average and shadow for min/max

Tags:

r

line-plot

I've made a quick example data frame for this below. Basically I want to create a line plot with the average value as a line and a shadow around that line representative of the range of the values. I realise I'll likely have to find row min/max but am unsure how to do this for rows and also don't know how I would go about plotting this

TEST <- data.frame(a=c(1,5,7,2), b=c(3,8,2,5), c=c(6,10,2,1))
TEST$mean <- rowMeans(TEST)

Any help appreciated - Thanks

like image 542
Darren J Avatar asked Aug 11 '14 13:08

Darren J


2 Answers

It is probably easily done with base R too, but here's a ggplot approach

Adding Min and Max and some index for the x axis

TEST <- transform(TEST, Min = pmin(a,b,c), Max = pmax(a,b,c), indx = seq_len(dim(TEST)[1]))

Plotting, using geom_ribbon

library(ggplot2)
ggplot(TEST) +
  geom_line(aes(indx, mean), group = 1) +
  geom_ribbon(aes(x = indx, ymax = Max, ymin = Min), alpha = 0.6, fill = "skyblue")

enter image description here

like image 110
David Arenburg Avatar answered Nov 06 '22 01:11

David Arenburg


Just to add another option, here's a possibile solution using only base R:

TEST <- data.frame(a=c(1,5,7,2), b=c(3,8,2,5), c=c(6,10,2,1))

# compute mean, min and max of rows
means <- rowMeans(TEST)
maxs <- apply(TEST,1,max)
mins <- apply(TEST,1,min)

# create x-coordinates
xcoords <- 1:nrow(TEST)

# create an empty plot to make space for everything 
plot(x=c(min(xcoords),max(xcoords)),y=c(min(mins),max(maxs)),
     type="n", main="Average",xlab="X",ylab="Y")

# add min-max ranges (color is DodgerBlue with 80/255 of opacity, 
# for rgb values of colors see http://en.wikipedia.org/wiki/Web_colors)
rangecolor <- rgb(30,144,255,alpha=80,maxColorValue=255)
polygon(x=c(xcoords,rev(xcoords)),y=c(maxs,rev(means)),col=rangecolor,border=NA)
polygon(x=c(xcoords,rev(xcoords)),y=c(mins,rev(means)),col=rangecolor,border=NA)

# add average line (black)
meancolor <- "black"
lines(x=xcoords,y=means,col=meancolor)

Result :

enter image description here

For future reuse, you can also wrap it into a helpful function :

plotLineWithRange <- function(x, yVal, yMin, yMax,
                          lineColor="Black", rangeColor="LightBlue",
                          main="", xlab="X", ylab="Y"){
  if(missing(x)){
    x <- 1:length(yVal)
  }
  stopifnot(length(yVal) == length(yMin) && length(yVal) == length(yMax))

  plot(x=c(min(x),max(x)),y=c(min(yMin),max(yMax)),type="n", main=main,xlab=xlab,ylab=ylab)
  polygon(x=c(x,rev(x)),y=c(yMax,rev(yVal)),col=rangeColor,border=NA)
  polygon(x=c(x,rev(x)),y=c(yMin,rev(yVal)),col=rangeColor,border=NA)
  lines(x=x,y=yVal,col=lineColor)
}


# usage example:
plotLineWithRange(yVal=means,yMin=mins,yMax=maxs,main="Average")
like image 29
digEmAll Avatar answered Nov 06 '22 02:11

digEmAll