Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Base R horizontal legend - with multiple rows

Tags:

r

I wish to create a horizontal legend with multiple rows using base R (not ggplot). There is an option for multiple columns but not multiple rows in legend(). Is there a way to do this? Example to play with below where the horizontal legend it too wide for the plot.

MyCol <- topo.colors(20)
barplot(rep(1,20), yaxt="n", col=MyCol)
x <- 1:20
MyLab <- paste("Zone",x)
legend("bottom",MyLab,fill=MyCol,horiz=T)
like image 793
Markm0705 Avatar asked Sep 17 '16 23:09

Markm0705


1 Answers

You can use the ncol = parameter instead of horiz to get the layout you want. Note that horiz overrides ncol, so don't use both together. Although, this does not specify the number of rows directly, it does do so indirectly, because the number of rows is determined by the number of columns and factors.

MyCol <- topo.colors(20)
barplot(rep(1,20), yaxt="n", col=MyCol)
x <- 1:20
MyLab <- paste("Zone",x)
legend("bottom",MyLab,fill=MyCol,ncol=5)

enter image description here

If you want to arrange the legend items ordered along rows, you can do this by indexing them in the order you want. E.g.

MyOrder = matrix(1:20, nrow = 4, ncol = 5, byrow = T)
legend("bottom",MyLab[MyOrder], fill=MyCol[MyOrder] ,ncol=5)

enter image description here

To generalize for different numbers of rows and factors, we can do something like

Nfact = 21
Nrows = 5
Ncols = ceiling(Nfact / Nrows)
MyOrder = matrix(1:(Nrows*Ncols), nrow=Nrows, ncol=Ncols, byrow=T)

MyCol <- topo.colors(Nfact)
x <- 1:Nfact
MyLab <- paste("Zone",x)

barplot(rep(1,Nfact), yaxt="n", col=MyCol)
legend("bottom", MyLab[MyOrder], fill = MyCol[MyOrder], ncol = Ncols, border=NA)

enter image description here

And a final extra trick: In the previous plot, we set border=NA. This is to prevent borders being drawn around empty legend items (those at the bottoms of incomplete columns). If you want borders, then we should also create a vector of border colours that is NA only in the locations we don't want to draw.

MyBorders = rep("black", Nrows*Ncols)
MyBorders[MyOrder > Nfact] <- NA
legend("bottom", MyLab[MyOrder], fill = MyCol[MyOrder], ncol = Ncols, border=MyBorders)

enter image description here

like image 56
dww Avatar answered Sep 20 '22 01:09

dww