0

I'd like to loop through a data.frame, organize the values from least to greatest, then make a bar plot showing the values. For this to be useful, I of course need to label the bars. Adapting a method from this SO answer, and looping through the variables, I get almost what I want:

for(nm in names(mtcars)){
  ord <- order(mtcars[nm])
  end_point = 0.5 + nrow(mtcars) + nrow(mtcars)-1   
  barplot(mtcars[ord, nm], main=paste(nm, " vs. model", sep=""), ylab=nm, xlab=1, space=1)
  text(seq(1.5,end_point,by=2), par("usr")[3]-0.25, 
       srt = 60, adj= 1, xpd = TRUE,
       labels = paste(rownames(mtcars)[ord]), cex=0.65)
}

Upon running the code, I found that the space between the x-axis and the label text varies considerably between plots, with the plots for "am" and "vs" being the worst offenders. Why is this happening, and how can I ensure that the labels are in a consistent place?

Community
  • 1
  • 1
Daniel Watkins
  • 1,631
  • 14
  • 16

1 Answers1

1

That's because due to the differing ranges, the scale of the user space changes with each plot. So a different of .25 means different things on different scales. So instead of using a raw .25 value, you should scale it to the user space. How about

for(nm in names(mtcars)){
  ord <- order(mtcars[nm])
  end_point = 0.5 + nrow(mtcars) + nrow(mtcars)-1   
  bp<-barplot(mtcars[ord, nm], main=paste(nm, " vs. model", sep=""), ylab=nm, xlab=1, space=1)
  text(seq(1.5,end_point,by=2), par("usr")[3]+grconvertY(1, from="inches", to="user"), 
       srt = 60, adj= 1, xpd = TRUE,
       labels = paste(rownames(mtcars)[ord]), cex=0.65)
}
MrFlick
  • 195,160
  • 17
  • 277
  • 295