Tal Galili
2009-Aug-12 09:47 UTC
[R] A function for plotting a boxplot with added dot and bars (for mean and SE) - please help improve my code
Hello people, A while back I wanted to plot boxplots with interactions that will have a dot for the mean of the sample + bars for the SE. After searching for some code, I found something that did it for one level, but couldn't find something that will allow for interactions the way the original boxplot does. After playing with the original code, I found a way for allowing the boxplot code to introduce interactions to it. The price for that was that I was forced to use a little different syntax for the function then that of the original boxplot. In order to use the function, one must use lists for the function input arguments, and until now I didn't find a way for doing the same task from a formula input. So for example, the original boxplot will be written like this: boxplot(y ~ A*B) Where as my function will look like this: boxplot.2(y , list(A,B) ) In this e-mail I am giving away the code for: 1) helping out others searching for this solution. and 2) in hope to have more experienced R programmers come by and improve on this code (by, for example, removing the for loop in it, or allowing to use a formula instead of a list input) Here is the code: boxplot.2 <- function(fo.head, list.fo.tail = list(1), print.mean = T, plot.CI = T, add.mean.sd.to.boxplot.names = T, plot.round.factor = 2 ,...) { require(gplots) tmp <- split(fo.head , list.fo.tail) means <- sapply(tmp, mean) stdev <- sqrt(sapply(tmp, var)) #IS right - because of the sqrt !!! <- sqrt(sapply(tmp, var)) # was var, I changed it to sd n <- sapply(tmp,length) ciw <- qt(0.975, n-1) * stdev / sqrt(n) old.names = attributes(tmp)$names length.of.names = length(old.names) new.names = as.list(old.names) for(i in c(1:length.of.names)) { new.names[[i]] <- paste(old.names[i], " (", round(means[i],plot.round.factor) ,",", round(ciw[i],plot.round.factor) ,")", sep = "") } if(add.mean.sd.to.boxplot.names) { if(length(list.fo.tail) == 1) { sub.text = paste("mean:", round(means,3), "(SE:",round(ciw,3), " ; N:" ,n, ")") boxplot(tmp, xlab = sub.text, cex.axis = min(1, mean(c(1,12/ max(nchar(new.names)) )) ), ...) } else { boxplot(tmp, names = new.names, cex.axis = min(1, mean(c(1,12/ max(nchar(new.names)) )) ), ...) } } else { boxplot(tmp, ...) } # else - make boxplot without them # adding the points and the bars points(means, col = 'red', pch = 19) if(require(gplots) & plot.CI) { plotCI(x=means, uiw=ciw, col="white", barcol="blue", xaxt="n" , add = T) } if(print.mean) { small.mean.and.se.table <- rbind(round(means,3),round(ciw,3), n) rownames(small.mean.and.se.table) <- c("means:", "SE's:", "N") print(t(small.mean.and.se.table)) } } # <-- end boxplot3 # Here is a small example: data(mtcars) head(mtcars) attach(mtcars) boxplot.2(mpg , list(round(wt), am) , data = mtcars, las = 2) Hope this will benefit others, and also hope that others will improve on this code and give it back to the community, Tal galili -- ---------------------------------------------- My contact information: Tal Galili Phone number: 972-50-3373767 FaceBook: Tal Galili My Blogs: http://www.r-statistics.com/ http://www.talgalili.com http://www.biostatistics.co.il [[alternative HTML version deleted]]
ONKELINX, Thierry
2009-Aug-12 10:29 UTC
[R] A function for plotting a boxplot with added dot and bars (formean and SE) - please help improve my code
This can be done much easier and transparent with ggplot2 library(ggplot2) ggplot(mtcars, aes(x = factor(round(wt)), y = mpg, colour = factor(am))) + geom_boxplot() + geom_point(stat = "summary", fun.y = "mean", position = position_dodge(width = 0.75)) HTH, Thierry ------------------------------------------------------------------------ ---- ir. Thierry Onkelinx Instituut voor natuur- en bosonderzoek / Research Institute for Nature and Forest Cel biometrie, methodologie en kwaliteitszorg / Section biometrics, methodology and quality assurance Gaverstraat 4 9500 Geraardsbergen Belgium tel. + 32 54/436 185 Thierry.Onkelinx at inbo.be www.inbo.be To call in the statistician after the experiment is done may be no more than asking him to perform a post-mortem examination: he may be able to say what the experiment died of. ~ Sir Ronald Aylmer Fisher The plural of anecdote is not data. ~ Roger Brinner The combination of some data and an aching desire for an answer does not ensure that a reasonable answer can be extracted from a given body of data. ~ John Tukey -----Oorspronkelijk bericht----- Van: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] Namens Tal Galili Verzonden: woensdag 12 augustus 2009 11:48 Aan: r-help at r-project.org Onderwerp: [R] A function for plotting a boxplot with added dot and bars (formean and SE) - please help improve my code Hello people, A while back I wanted to plot boxplots with interactions that will have a dot for the mean of the sample + bars for the SE. After searching for some code, I found something that did it for one level, but couldn't find something that will allow for interactions the way the original boxplot does. After playing with the original code, I found a way for allowing the boxplot code to introduce interactions to it. The price for that was that I was forced to use a little different syntax for the function then that of the original boxplot. In order to use the function, one must use lists for the function input arguments, and until now I didn't find a way for doing the same task from a formula input. So for example, the original boxplot will be written like this: boxplot(y ~ A*B) Where as my function will look like this: boxplot.2(y , list(A,B) ) In this e-mail I am giving away the code for: 1) helping out others searching for this solution. and 2) in hope to have more experienced R programmers come by and improve on this code (by, for example, removing the for loop in it, or allowing to use a formula instead of a list input) Here is the code: boxplot.2 <- function(fo.head, list.fo.tail = list(1), print.mean = T, plot.CI = T, add.mean.sd.to.boxplot.names = T, plot.round.factor = 2 ,...) { require(gplots) tmp <- split(fo.head , list.fo.tail) means <- sapply(tmp, mean) stdev <- sqrt(sapply(tmp, var)) #IS right - because of the sqrt !!! <- sqrt(sapply(tmp, var)) # was var, I changed it to sd n <- sapply(tmp,length) ciw <- qt(0.975, n-1) * stdev / sqrt(n) old.names = attributes(tmp)$names length.of.names = length(old.names) new.names = as.list(old.names) for(i in c(1:length.of.names)) { new.names[[i]] <- paste(old.names[i], " (", round(means[i],plot.round.factor) ,",", round(ciw[i],plot.round.factor) ,")", sep = "") } if(add.mean.sd.to.boxplot.names) { if(length(list.fo.tail) == 1) { sub.text = paste("mean:", round(means,3), "(SE:",round(ciw,3), " ; N:" ,n, ")") boxplot(tmp, xlab = sub.text, cex.axis = min(1, mean(c(1,12/ max(nchar(new.names)) )) ), ...) } else { boxplot(tmp, names = new.names, cex.axis = min(1, mean(c(1,12/ max(nchar(new.names)) )) ), ...) } } else { boxplot(tmp, ...) } # else - make boxplot without them # adding the points and the bars points(means, col = 'red', pch = 19) if(require(gplots) & plot.CI) { plotCI(x=means, uiw=ciw, col="white", barcol="blue", xaxt="n" , add = T) } if(print.mean) { small.mean.and.se.table <- rbind(round(means,3),round(ciw,3), n) rownames(small.mean.and.se.table) <- c("means:", "SE's:", "N") print(t(small.mean.and.se.table)) } } # <-- end boxplot3 # Here is a small example: data(mtcars) head(mtcars) attach(mtcars) boxplot.2(mpg , list(round(wt), am) , data = mtcars, las = 2) Hope this will benefit others, and also hope that others will improve on this code and give it back to the community, Tal galili -- ---------------------------------------------- My contact information: Tal Galili Phone number: 972-50-3373767 FaceBook: Tal Galili My Blogs: http://www.r-statistics.com/ http://www.talgalili.com http://www.biostatistics.co.il [[alternative HTML version deleted]] ______________________________________________ R-help at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code. Dit bericht en eventuele bijlagen geven enkel de visie van de schrijver weer en binden het INBO onder geen enkel beding, zolang dit bericht niet bevestigd is door een geldig ondertekend document. The views expressed in this message and any annex are purely those of the writer and may not be regarded as stating an official position of INBO, as long as the message is not confirmed by a duly signed document.