Highlighting significant results from non-parametric multiple comparisons on boxplots I have box plots of 13 groups that I show in one plot. The groups have unbalanced populations and are not normally distributed. I want to show which pairs are statistically similar (i.e., have kruskal.test p-value < 0.05) by putting a,b,c, etc. on top of boxes that match.
Here is a pseudo code to show what I have:
A = c(1, 5, 8, 17, 16, 3, 24, 19, 6) 
B = c(2, 16, 5, 7, 4, 7, 3) 
C = c(1, 1, 3, 7, 9, 6, 10, 13) 
D = c(2, 15, 2, 9, 7) 
junk = list(g1=A, g2=B, g3=C, g4=D) 
boxplot(junk) 

Here is an plot I found that does what I want (except I have 13 groups in one row):

 A: The simplest code that comes to my mind is shown below. I'm pretty certain there's some already existing function(s) to do that on CRAN but I'm too lazy to search for them, even on R-seek.
dd <- data.frame(y=as.vector(unlist(junk)), 
                 g=rep(paste("g", 1:4, sep=""), unlist(lapply(junk, length))))

aov.res <- kruskal.test(y ~ g, data=dd)
alpha.level <- .05/nlevels(dd$g)  # Bonferroni correction, but use 
                                  # whatever you want using p.adjust()

# generate all pairwise comparisons
idx <- combn(nlevels(dd$g), 2)

# compute p-values from Wilcoxon test for all comparisons
pval.res <- numeric(ncol(idx))
for (i in 1:ncol(idx))
  # test all group, pairwise
  pval.res[i] <- with(dd, wilcox.test(y[as.numeric(g)==idx[1,i]], 
                                      y[as.numeric(g)==idx[2,i]]))$p.value

# which groups are significantly different (arranged by column)
signif.pairs <- idx[,which(pval.res<alpha.level)]

boxplot(y ~ g, data=dd, ylim=c(min(dd$y)-1, max(dd$y)+1))
# use offset= to increment space between labels, thanks to vectorization
for (i in 1:ncol(signif.pairs))
    text(signif.pairs[,i], max(dd$y)+1, letters[i], pos=4, offset=i*.8-1)

Here is an example of what the above code would produce (with significant differences between the four groups):

Instead of the Wilcoxon test, one could rely on the procedure implemented in the kruskalmc() function from the pgirmess package (see a description of the procedure used here).
Also, be sure to check Rudolf Cardinal's R tips about R: basic graphs 2 (see in particular, Another bar graph, with annotations).
