Alexis
Alexis

Reputation: 852

How to add a column of labels to the right of a plot

I have code producing a swell plot in R. Check it out!

A swell plot in R

I made it using this code:

SwellPlot <- function(Data,P) {
  par(mfcol=c(1,1), mar=c(4, 4.5, 0, 0) + 0.1)
  plot(c(0.5,P+0.5), c(-0.5,P+0.5), type="n", cex=1, lab=c(20,20,1), cex.lab=1.5, yaxs="i", xaxs="i", xlab=~bold("Stuff!"), ylab=~bold("Other stuff!"))
  for (f in 1:(P+1)) {
      for (r in 0:P) {
          points(r,(f-1), pch=15, cex=(60/P)*sqrt(Data[f,r]/200))
          }
      }
  }

With Data input as a matrix, like this one used for the above example:

Data <- matrix(c(0, 117, 76, 7, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 199, 1, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 188, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 90, 
109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 38, 143, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 18, 142, 39, 1, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 8, 114, 75, 3, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 4, 95, 99, 2, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 68, 121, 7, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 65, 122, 10, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 
120, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
2, 42, 132, 23, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 35, 135, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 44, 128, 27, 1, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 33, 139, 27, 1, 0, 0, 0, 0, 
0, 0, 0, 0), 17, 16, byrow=FALSE)

I would like to glom a vertical series of labels along the right side of my swell plot (these labels are different than the y-axis labels, which I need to remain as they already are). I have done so by extending the x-axis and using text(), but when I do this it looks kludgy (on the x-axis labels) and because I have plots with quite variable x-axis lengths I have to spend a lot of trial and error time making sure that the width of my labels does not overlap the right-most plotted elements. The improved plot would look kinda like this:

Mock-up of an even sweller plot!

I imagine that there must be some relatively straightforward way of doing this using layout() or mfcol or somesuch, but the documentation and examples get rapidly complex for me. How would you solve this?

Bonus points for answers that permit me to specifically (1) make the width of the label column I would like to add 8% of the width of my swell plot, and (2) make my swell plot (not including the labels up the right side) retain its 1:1 aspect ratio.

Also bonus points if this can be done using par and plot and the like.

Upvotes: 0

Views: 155

Answers (1)

MrFlick
MrFlick

Reputation: 206242

Here is one possibility. You can either add rownames to your Data or you can pass in a vector of names

SwellPlot <- function(Data,P=nrow(Data), labels=!is.null(rownames(Data))) {
  par(mfcol=c(1,1), mar=c(4, 4.5, 0, 3) + 0.1)
  plot(c(0.5,P+0.5), c(-0.5,P+0.5), 
      type="n", cex=1, lab=c(20,20,1), 
      cex.lab=1.5, yaxs="i", xaxs="i", 
      xlab=~bold("Stuff!"), ylab=~bold("Other stuff!")
  )
  cex<-(60/P)*sqrt(Data/200)
  points(col(Data), row(Data), pch=15, cex=cex)
  if(is.logical(labels) && labels) {
    labels = rownames(Data)
  }
  if(is.character(labels)) {
    axis(4, labels=labels, at=1:P, las=1, tick=F)
  }
} 

#add names for labeling
lbl<-c("",rev(c("Ant","Bat","Cat","Dog","Eel","Fly","Gar","Hog")), rep("",8))
rownames(Data)<-lbl
SwellPlot(Data)

swell plot

I just drew the extra names with axis and I made sure to make room for them by adjusting the par

I also edited the middle to take out the two loops. Those were pretty slow. You can do it all with one call to points passing all the x,y pairs at once. The trick is that if you pass a data.frame, it will convert it to a simple vector. So if all the matrices are arranges the same way, you'll get a point for each cell.

Upvotes: 1

Related Questions