vioplot/0000755000176200001440000000000013570256242011754 5ustar liggesusersvioplot/NAMESPACE0000755000176200001440000000137413570226236013203 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method(vioplot,default) S3method(vioplot,formula) export(vioplot) import(sm) importFrom(grDevices,boxplot.stats) importFrom(grDevices,dev.flush) importFrom(grDevices,dev.hold) importFrom(grDevices,dev.interactive) importFrom(grDevices,devAskNewPage) importFrom(grDevices,xy.coords) importFrom(graphics,Axis) importFrom(graphics,axis) importFrom(graphics,box) importFrom(graphics,lines) importFrom(graphics,par) importFrom(graphics,plot.new) importFrom(graphics,plot.window) importFrom(graphics,plot.xy) importFrom(graphics,points) importFrom(graphics,polygon) importFrom(graphics,rect) importFrom(graphics,title) importFrom(stats,median) importFrom(stats,na.omit) importFrom(stats,quantile) importFrom(zoo,rollmean) vioplot/LICENSE0000644000176200001440000000012113507646542012761 0ustar liggesusersYEAR: 2004 COPYRIGHT HOLDER: Daniel Adler ORGANIZATION: University of Goettingen vioplot/man/0000755000176200001440000000000013570226443012527 5ustar liggesusersvioplot/man/vioplot.Rd0000755000176200001440000002726613570226443014532 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/vioplot.R \name{vioplot} \alias{vioplot} \alias{vioplot.formula} \alias{vioplot.default} \title{violin plot} \usage{ \method{vioplot}{formula}( formula, data = NULL, ..., subset, na.action = NULL, add = FALSE, ann = !add, horizontal = FALSE, xlab = mklab(y_var = horizontal), ylab = mklab(y_var = !horizontal), names = NULL, drop = FALSE, sep = ".", lex.order = FALSE ) \method{vioplot}{default}( x, ..., data = NULL, range = 1.5, h = NULL, ylim = NULL, names = NULL, horizontal = FALSE, col = "grey50", border = par()$fg, lty = 1, lwd = 1, rectCol = par()$fg, lineCol = par()$fg, pchMed = 19, colMed = "white", colMed2 = "grey 75", at, add = FALSE, wex = 1, drawRect = TRUE, areaEqual = FALSE, axes = TRUE, frame.plot = axes, panel.first = NULL, panel.last = NULL, asp = NA, main = "", sub = "", xlab = NA, ylab = NA, line = NA, outer = FALSE, xlog = NA, ylog = NA, adj = NA, ann = NA, ask = NA, bg = NA, bty = NA, cex = NA, cex.axis = NA, cex.lab = NA, cex.main = NA, cex.names = NULL, cex.sub = NA, cin = NA, col.axis = NA, col.lab = NA, col.main = NA, col.sub = NA, cra = NA, crt = NA, csi = NA, cxy = NA, din = NA, err = NA, family = NA, fg = NA, fig = NA, fin = NA, font = NA, font.axis = NA, font.lab = NA, font.main = NA, font.sub = NA, lab = NA, las = NA, lend = NA, lheight = NA, ljoin = NA, lmitre = NA, mai = NA, mar = NA, mex = NA, mfcol = NA, mfg = NA, mfrow = NA, mgp = NA, mkh = NA, new = NA, oma = NA, omd = NA, omi = NA, page = NA, pch = NA, pin = NA, plt = NA, ps = NA, pty = NA, smo = NA, srt = NA, tck = NA, tcl = NA, usr = NA, xaxp = NA, xaxs = NA, xaxt = NA, xpd = NA, yaxp = NA, yaxs = NA, yaxt = NA, ylbias = NA, log = "", logLab = c(1, 2, 5), na.action = NULL, na.rm = T, side = "both", plotCentre = "point" ) } \arguments{ \item{x}{for specifying data from which the boxplots are to be produced. Either a numeric vector, or a single list containing such vectors. Additional unnamed arguments specify further data as separate vectors (each corresponding to a component boxplot). NAs are allowed in the data.} \item{...}{additional data vectors or formula parameters. For the formula method, named arguments to be passed to the default method.} \item{formula}{a formula, such as y ~ grp, where y is a numeric vector of data values to be split into groups according to the grouping variable grp (usually a factor).} \item{data}{a data.frame (or list) from which the variables in formula should be taken.} \item{subset}{an optional vector specifying a subset of observations to be used for plotting.} \item{na.action}{a function which indicates what should happen when the data contain NAs. The default is to ignore missing values in either the response or the group.} \item{add}{logical. if FALSE (default) a new plot is created} \item{horizontal}{logical. horizontal or vertical violins} \item{names}{one label, or a vector of labels for the data must match the number of data given} \item{drop, sep, lex.order}{defines groups to plot from formula, passed to \code{\link[base]{split.default}}, see there.} \item{range}{a factor to calculate the upper/lower adjacent values} \item{h}{the height for the density estimator, if omit as explained in sm.density, h will be set to an optimum} \item{ylim}{y limits} \item{col}{Graphical parameter for fill colour of the violin(s) polygon. NA for no fill colour. If col is a vector, it specifies the colour per violin, and colours are reused if necessary.} \item{border}{Graphical parameters for the colour of the violin border passed to lines. NA for no border. If border is a vector, it specifies the colour per violin, and colours are reused if necessary.} \item{lty, lwd}{Graphical parameters for the violin passed to lines and polygon} \item{rectCol}{Graphical parameters to control fill colour of the box. NA for no fill colour. If col is a vector, it specifies the colour per violin, and colours are reused if necessary.} \item{lineCol}{Graphical parameters to control colour of the box outline and whiskers. NA for no border. If lineCol is a vector, it specifies the colour per violin, and colours are reused if necessary.} \item{pchMed}{Graphical parameters to control shape of the median point. If pchMed is a vector, it specifies the shape per violin.} \item{colMed, colMed2}{Graphical parameters to control colour of the median point. If colMed is a vector, it specifies the colour per violin. colMed specifies the fill colour in all cases unless pchMed is 21:25 in which case colMed is the border colour and colMed2 is the fill colour.} \item{at}{position of each violin. Default to 1:n} \item{wex}{relative expansion of the violin. If wex is a vector, it specifies the area/width size per violin and sizes are reused if necessary.} \item{drawRect}{logical. The box is drawn if TRUE.} \item{areaEqual}{logical. Density plots checked for equal area if TRUE. wex must be scalar, relative widths of violins depend on area.} \item{axes, frame.plot, panel.first, panel.last, asp, line, outer, adj, ann, ask, bg, bty, cin, col.axis, col.lab, col.main, col.sub, cra, crt, csi, cxy, din, err, family, fg, fig, fin, font, font.axis, font.lab, font.main, font.sub, lab, las, lend, lheight, ljoin, lmitre, mai, mar, mex, mfcol, mfg, mfrow, mgp, mkh, new, oma, omd, omi, page, pch, pin, plt, ps, pty, smo, srt, tck, tcl, usr, xlog, xaxp, xaxs, xaxt, xpd, yaxp, yaxs, ylbias}{Arguments to be passed to methods, such as graphical parameters (see \code{\link[graphics]{par}})).} \item{main, sub, xlab, ylab}{graphical parameters passed to plot.} \item{ylog}{A logical value (see log in \code{\link[graphics]{plot.default}}). If TRUE, a logarithmic scale is in use (e.g., after plot(*, log = "y")). For a new device, it defaults to FALSE, i.e., linear scale.} \item{cex}{A numerical value giving the amount by which plotting text should be magnified relative to the default.} \item{cex.axis}{The magnification to be used for y axis annotation relative to the current setting of cex.} \item{cex.lab}{The magnification to be used for x and y labels relative to the current setting of cex.} \item{cex.main}{The magnification to be used for main titles relative to the current setting of cex.} \item{cex.names}{The magnification to be used for x axis annotation relative to the current setting of cex. Takes the value of cex.axis if not given.} \item{cex.sub}{The magnification to be used for sub-titles relative to the current setting of cex.} \item{yaxt}{A character which specifies the y axis type. Specifying "n" suppresses plotting.} \item{log}{Logarithmic scale if log = "y" or TRUE. Invokes ylog = TRUE.} \item{logLab}{Increments for labelling y-axis on log-scale, defaults to numbers starting with 1, 2, 5, and 10.} \item{na.rm}{logical value indicating whether NA values should be stripped before the computation proceeds. Defaults to TRUE.} \item{side}{defaults to "both". Assigning "left" or "right" enables one sided plotting of violins. May be applied as a scalar across all groups.} \item{plotCentre}{defaults to "points", plotting a central point at the median. If "line" is given a median line is plotted (subject to side) alternatively.} } \description{ Produce violin plot(s) of the given (grouped) values with enhanced annotation and colour per group. Includes customisation of colours for each aspect of the violin, boxplot, and separate violins. This supports input of data as a list or formula, being backwards compatible with \code{\link[vioplot]{vioplot}} (0.2) and taking input in a formula as used for \code{\link[graphics]{boxplot}}. } \examples{ # box- vs violin-plot par(mfrow=c(2,1)) mu<-2 si<-0.6 bimodal<-c(rnorm(1000,-mu,si),rnorm(1000,mu,si)) uniform<-runif(2000,-4,4) normal<-rnorm(2000,0,3) vioplot(bimodal,uniform,normal) boxplot(bimodal,uniform,normal) # add to an existing plot x <- rnorm(100) y <- rnorm(100) plot(x, y, xlim=c(-5,5), ylim=c(-5,5)) vioplot(x, col="tomato", horizontal=TRUE, at=-4, add=TRUE,lty=2, rectCol="gray") vioplot(y, col="cyan", horizontal=FALSE, at=-4, add=TRUE,lty=2) # formula input data("iris") vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col=c("lightgreen", "lightblue", "palevioletred")) legend("topleft", legend=c("setosa", "versicolor", "virginica"), fill=c("lightgreen", "lightblue", "palevioletred"), cex = 0.5) data("diamonds", package = "ggplot2") palette <- RColorBrewer::brewer.pal(9, "Pastel1") par(mfrow=c(3, 1)) vioplot(price ~ cut, data = diamonds, las = 1, col = palette) vioplot(price ~ clarity, data = diamonds, las = 2, col = palette) vioplot(price ~ color, data = diamonds, las = 2, col = palette) par(mfrow=c(3, 1)) #generate example data data_one <- rnorm(100) data_two <- rnorm(50, 1, 2) #generate violin plot with similar functionality to vioplot vioplot(data_one, data_two, col="magenta") #note vioplox defaults to a greyscale plot vioplot(data_one, data_two) #colours can be customised separately, with axis labels, legends, and titles vioplot(data_one, data_two, col=c("red","blue"), names=c("data one", "data two"), main="data violin", xlab="data class", ylab="data read") legend("topleft", fill=c("red","blue"), legend=c("data one", "data two")) #colours can be customised for the violin fill and border separately vioplot(data_one, data_two, col="grey85", border="purple", names=c("data one", "data two"), main="data violin", xlab="data class", ylab="data read") #colours can also be customised for the boxplot rectange and lines (border and whiskers) vioplot(data_one, data_two, col="grey85", rectCol="lightblue", lineCol="blue", border="purple", names=c("data one", "data two"), main="data violin", xlab="data class", ylab="data read") #these colours can also be customised separately for each violin vioplot(data_one, data_two, col=c("skyblue", "plum"), rectCol=c("lightblue", "palevioletred"), lineCol="blue", border=c("royalblue", "purple"), names=c("data one", "data two"), main="data violin", xlab="data class", ylab="data read") #this applies to any number of violins, given that colours are provided for each vioplot(data_one, data_two, rnorm(200, 3, 0.5), rpois(200, 2.5), rbinom(100, 10, 0.4), col=c("red", "orange", "green", "blue", "violet"), rectCol=c("palevioletred", "peachpuff", "lightgreen", "lightblue", "plum"), lineCol=c("red4", "orangered", "forestgreen", "royalblue", "mediumorchid"), border=c("red4", "orangered", "forestgreen", "royalblue", "mediumorchid"), names=c("data one", "data two", "data three", "data four", "data five"), main="data violin", xlab="data class", ylab="data read") #The areaEqual parameter scales with width of violins #Violins will have equal density area (including missing tails) rather than equal maximum width vioplot(data_one, data_two, areaEqual=TRUE) vioplot(data_one, data_two, areaEqual=TRUE, col=c("skyblue", "plum"), rectCol=c("lightblue", "palevioletred"), lineCol="blue", border=c("royalblue", "purple"), names=c("data one", "data two"), main="data violin", xlab="data class", ylab="data read") vioplot(data_one, data_two, rnorm(200, 3, 0.5), rpois(200, 2.5), rbinom(100, 10, 0.4), areaEqual=TRUE, col=c("red", "orange", "green", "blue", "violet"), rectCol=c("palevioletred", "peachpuff", "lightgreen", "lightblue", "plum"), lineCol=c("red4", "orangered", "forestgreen", "royalblue", "mediumorchid"), border=c("red4", "orangered", "forestgreen", "royalblue", "mediumorchid"), names=c("data one", "data two", "data three", "data four", "data five"), main="data violin", xlab="data class", ylab="data read") } \keyword{graphics} \keyword{plot} \keyword{violin} vioplot/DESCRIPTION0000755000176200001440000000206213570256242013465 0ustar liggesusersPackage: vioplot Title: Violin Plot Version: 0.3.4 Date: 2019-11-30 Authors@R: c(person("Daniel", "Adler", email = "dadler@uni-goettingen.de", role = c("aut", "cph")), person("S. Thomas", "Kelly", email = "tom.kelly@riken.jp", role = c("aut", "cre")), person("Tom M.", "Elliott", email = "tom.elliott@auckland.ac.nz", role = c("ctb"))) Description: A violin plot is a combination of a box plot and a kernel density plot. This package allows extensive customisation of violin plots. Depends: sm, zoo License: BSD_3_clause + file LICENSE URL: https://github.com/TomKellyGenetics/vioplot BugReports: https://github.com/TomKellyGenetics/vioplot/issues LazyData: true RoxygenNote: 7.0.1 Suggests: ggplot2, RColorBrewer, knitr, rmarkdown, testthat Language: en-GB VignetteBuilder: knitr Encoding: UTF-8 NeedsCompilation: no Packaged: 2019-11-29 14:54:09 UTC; tom Author: Daniel Adler [aut, cph], S. Thomas Kelly [aut, cre], Tom M. Elliott [ctb] Maintainer: S. Thomas Kelly Repository: CRAN Date/Publication: 2019-11-29 18:00:02 UTC vioplot/build/0000755000176200001440000000000013570230421013042 5ustar liggesusersvioplot/build/vignette.rds0000644000176200001440000000055313570230421015404 0ustar liggesusersSAK0m2K=ړ'o"$Hdk}׾u ! paZI:<JeOq)6*#?QY<;TN0n+-pЩTޫdJvJ_:ށE_h"(UHpss*u5fBBq墁%g-w՞;Q]/^iORk7{$ʓT=vl ,JX5mC! `dž7)O";G\ rN-lh,,؍a$|!ᄚvioplot/tests/0000755000176200001440000000000013411056063013107 5ustar liggesusersvioplot/tests/testthat/0000755000176200001440000000000013570256242014756 5ustar liggesusersvioplot/tests/testthat/test_ylog.R0000755000176200001440000000743313507766533017135 0ustar liggesuserslibrary("vioplot") context("log-scale") test_that("plot defaults", { data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) }) ##y-axis log scale (ylog) test_that("log-scale y-axis with ylog TRUE", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", ylog = T) }) test_that("linear y-axis with ylog FALSE", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", ylog = F) }) ##y-axis log scale (log=TRUE) test_that("log-scale y-axis with log TRUE", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = T) }) test_that("linear y-axis with log FALSE", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = F) }) test_that("override with ylog TRUE", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = F, ylog=T) }) ##y-axis log scale (log="y") test_that("log-scale y-axis with log='y'", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = 'y') }) test_that("log-scale y-axis with log='xy'", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = 'xy') }) test_that("linear y-axis with log=''", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = '') }) test_that("linear y-axis with log='x'", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = 'x') }) test_that("override with ylog TRUE", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = 'x', ylog=T) }) ##y-axis removed test_that("linear scale y-axis with labels removed", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", ylog = F, yaxt="n") }) test_that("log-scale y-axis with labels removed", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", ylog = T, yaxt="n") }) vioplot/tests/testthat/test_violin_median.R0000755000176200001440000000514613411056063020757 0ustar liggesuserslibrary("vioplot") context("side option") test_that("plot with left and right side options and median point", { data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="magenta", side ="left") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="magenta", side ="right") }) test_that("plot with both sides and median line", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="magenta", side ="both", plotCentre = "line") }) test_that("plot with left and right side options and median line", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="magenta", side ="left", plotCentre = "line") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="magenta", side ="right", plotCentre = "line") }) test_that("plot with areaEqual options and median line", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="magenta", side ="both", plotCentre = "line", areaEqual = T) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="magenta", side ="left", plotCentre = "line", areaEqual = T) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="magenta", side ="right", plotCentre = "line", areaEqual = T) }) vioplot/tests/testthat/test_violin_formula.R0000755000176200001440000000233613411056063021165 0ustar liggesuserslibrary("vioplot") context("formula input") test_that("plot data list input", { data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length") }) test_that("plot vector formula input", { boxplot(iris$Sepal.Length~iris$Species) vioplot(iris$Sepal.Length~iris$Species) }) test_that("plot column formula with dataframe input", { boxplot(Sepal.Length~Species, data=iris) vioplot(Sepal.Length~Species, data=iris) }) test_that("plot formula with dataframe input and scalar colour", { vioplot(Sepal.Length~Species, data=iris, col="lightblue") }) test_that("plot formula with dataframe input and vector colour", { vioplot(Sepal.Length~Species, data=iris, col=c("lightgreen", "lightblue", "palevioletred")) }) # attach(iris) # iris <- as.matrix(iris[,1:4]) # test_that("plot column formula with matrix input", { # vioplot(Sepal.Length~Species, data=iris) # }) vioplot/tests/testthat/test_violin_customisation.R0000755000176200001440000000651513411056063022424 0ustar liggesuserslibrary("vioplot") context("color custom and vectorised") test_that("plot with defaults and scalar colours", { data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="magenta") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue") }) #Vectorisation test_that("plot with vector colours", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col=c("lightgreen", "lightblue", "palevioletred")) legend("topleft", legend=c("setosa", "versicolor", "virginica"), fill=c("lightgreen", "lightblue", "palevioletred"), cex = 0.5) }) ## Plot colours: Violin Lines and Boxplot test_that("plot with scalar border", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue", border="royalblue") }) test_that("plot with scalar boxplot modifications", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", rectCol="palevioletred", lineCol="violetred") }) test_that("plot with scalar median colour", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", colMed="violet") }) ### Combined customisation test_that("plot with combined scalar customisation", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue", border="royalblue", rectCol="palevioletred", lineCol="violetred", colMed="violet") }) ### Vectorisation test_that("plot with combined vector customisation", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T, col=c("lightgreen", "lightblue", "palevioletred"), border=c("darkolivegreen4", "royalblue4", "violetred4"), rectCol=c("forestgreen", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), colMed=c("green", "cyan", "magenta"), pchMed=c(15, 17, 19)) }) vioplot/tests/testthat/test_violin_side.R0000755000176200001440000000146113411056063020442 0ustar liggesuserslibrary("vioplot") context("side option") test_that("plot with left and right side options", { data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="magenta", side ="left") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="magenta", side ="right") }) vioplot/tests/testthat/test_violin_names.R0000755000176200001440000000067013411056063020622 0ustar liggesuserslibrary("vioplot") context("names input") test_that("list input", { data(iris) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("a", "b", "c")) }) test_that("naming formulae", { data(iris) vioplot(iris$Sepal.Length~iris$Species, names=c("a", "b", "c")) vioplot(Sepal.Length~Species, data=iris, names=c("a", "b", "c")) }) vioplot/tests/testthat/Rplots.pdf0000644000176200001440000073274613567766147016777 0ustar liggesusers%PDF-1.4 %ρ\r 1 0 obj << /CreationDate (D:20191129004854) /ModDate (D:20191129004854) /Title (R Graphics Output) /Producer (R 3.6.1) /Creator (R) >> endobj 2 0 obj << /Type /Catalog /Pages 3 0 R >> endobj 7 0 obj << /Type /Page /Parent 3 0 R /Contents 8 0 R /Resources 4 0 R >> endobj 8 0 obj << /Length 712 /Filter /FlateDecode >> stream xVMO1W5]WPJ4+8TiZIE~ǞD.K̋ W`5j4Tz)byу2h:;s g>N3dna'n|ܞt>2\al [3Mڈ# z?nulWlwއ1 xZK-Ed9ُkk׸S7-%SK)}ݯV["_|v[.?tG)Nwfc)8G̗ˏ?w)U@bC"ĥl5y$?endstream endobj 9 0 obj << /Type /Page /Parent 3 0 R /Contents 10 0 R /Resources 4 0 R >> endobj 10 0 obj << /Length 4200 /Filter /FlateDecode >> stream xZM^ ?.aZ敺@,JJDRѿs } ę1c>׷/W[ҨwMxt/z|o#!gſ|WWG_-z3^zn<ֳޡu7z ևyku7^oM{ͽ.0{}xigwO?]1?_4Yqӛ#ӷ?>By{Ç2n'O^~S۸.RV+.M%߮5ۣ[H7n0K'X^{$1Vw|ϝ$@k_~WG߼}WaRw㫷~ݫkC'ӽy(NSU\I9/~˘jZVRީ^)Dxadl0|0Bc0S0s2T7StW|5 3Sa"bwؙ[l=6B rG_wAQu !>$ 1Tv_bhwuZ" l; 8HGt'xk|^y*~nPϾ^) ]V^Fd 3Fz wupv_?zla6(j fj|-*3 BtvddVV'M8l[nQA\:n‹Z #eb9"3nc9n¨=vGuE" cDm2%}fv0'"pJyĝxq#zut{cdNJIV=d`X3#ZY@;Bxڙg [4=d[2VQD( :}s#G aw p>@j1ё<G2@e2ҧ n`^˓1z- k npF@**σzUݹ!ਗ਼plg!'qaጀδ`6`0lTm5_oHJ26Z_τ:#cƃg}P1>fYI} s0Az6/x6 )m<;υ\鈍'حxdt൘7A7)x/v+_@@וOE=V;AIt38$|]|bX|Q".>J#ϳV2jZt[0lh/:Ȓ&vI8+db$؊w8QDw kg<,1Ql]v-q/>卶Տő61k'ϓ"0_gY-mWܚ̇`o@S Q=_XKr(&U1GmU+آC+^/Pb({)N;)NŚ.E `1>Kf#4Vu jl vö %ճ%|d>L@|5@(Z5\zz6psՑv1Ql2dM&L}vʆz=Z&)?5;;,?e{||oejaw8JMafp) :oE4 J5;HaEVe08ـECA‹ I'H(LRLhKFF APV+ n%tMP+ I lҢ yBHI K$icvQJ" 6!t{ @v(~ d䣨&.ILuHPD".~tQREAw'!vv^BFMF۰lQ=YhhO1qP-(3h+~O8" nv0R~Mm$U|HD6'I-yH^-ku6';&Ifæ'&*ux f^j8ĊO`1 2lQO,aD'Np?b i/~25+7mI1?e?%M;ua/~ܸ l}##EXRK&|hlzOT{he={ 0нgcjpj<b-Ohuzx-67I7S;$zċG<ٍ?wAcOͦp&ѱɇ)|I3'Ju1mk55\{=mU Ifea: mzDYhף m;"qK`S[ҶǨǴm(35O~?3혶^'/z Aƶ+37:#n=D^z6T=~Mu;٤৯݁*ϵ[ l Yn"B^ooK f2:J8m:wvOcA?isFP6oyfF(myksLAް}lEv<P\_ΠdYR.zhrK63br*3 꿙xu('ѲC6]6mol'ن,^}E\2ݮGy%0y9 G[_v弹mkf4MNmSf%7ԓGnSUӴ>f|۱n~1؟PދϠT}cUr!V5i_ac$ QAxC3^v}r [tI^޳ )\gV'|E|P똑?qh&?UC îLu=m$z7^uO~xey4uW)m<^]ta9AxuSxeǛv;+q' okxT$2g╎AaXxvw]9;4c |d:s&"^gj2"\q;{ Ce_ߨ')ǕJTL.S?Ӄ/U /OUۃoM>ϊnOz<\{Q/l=zb]o|Gzd^zQx>;g=9njG=Uz~[`;35UtsƗЬWEK>@<]z0"ЭGK 3ꧩw?V/=4w%;Su- c$&[wl#ѤCjPo^`˗4"[o/Wio^\zOp/^6N=tvpbjԶ^?GAKo*~%OkWw5~Ȇ'x3UQ~ݲ"X&n)snĿnL_aendstream endobj 11 0 obj << /Type /Page /Parent 3 0 R /Contents 12 0 R /Resources 4 0 R >> endobj 12 0 obj << /Length 4156 /Filter /FlateDecode >> stream xZ^Oqa%PRqbd`#ꞛG9TWWor^5ݪF\;5/zٓpO>_~u_}yC Nz5^zxw{k|c\]t;<{U=4x=pc>#O$8?_4YqWGz珯>=XN;|=9??R˯x4qS*w+v{oOM%߮IH5cj'ݐタwS>V%P-R,8׏b/?K7o_z=,Ul~|_<[:Ճ/+h߁'隆GT+Eo՘0~jdP]2&HAq1"|4n}@5qIiWowmqjnIkw|3bDՁ}>8y؆Taٱ%-xsO܏ % 1Б8OAHrEW  `3Ղ$&uw^_^x^hЋdzG7/=q`zz JC/ :p!nw @O\/ŗ8RY *)!!@OB0 9ކ^Pq?hs-A ,8V׋dVC(Ks/8lc 0yt\x }.|{=P]8_jim栗^Pń}}0O<7v~î|f[|fa3s= I}\LX]VCw<gg[^@5z7|#`Ld2gn;"fK[/\]N=3.Sρ[iǝ/%O8P||D\|ϲ%ڝv>ċ+_f;ȝOVX㑯1Q;g3+`! <~l0^NLL6~sleKoeDzװϩ{|G=$UxeQ |,.0Zce4ii`wmt8 h:Űm#&*SJ.HK5 ˇrsWyac'L>Y lGQ"}vU+@xo.3x/R@guax x% Rrq m. 䖤d%nITRE &:U zb1"f,$k4Y)>`[j'Ol&O|ޏcjyGA=[Τ)rA0Cܮ_'"OL  le)u >%sx$gOA<8Ԉ$|Dvă|zZ| aRyt>0mm 6LL'&̧M+Nj@?p0쐅O4 , x'8Oj=!)VY#E|)KqBn2&6(KIZ!{+C8>W榅%ă XWO4Ջ өO: Iba_wϫ}8=jB Ѝ˱^pG5߹s!rGj-y~w&C&KnYl6HR9ڬ@|oVDx`G1 oxl;^Ϭ|P;C/'߿;E+~k釞aa;r!g<zڭzˍKsKng}\H\'+#Ñψy31|H̏D3_Sg>5,;G>&~|M63`LD~_~Ϧ+8?gHr~w)5~ |NckN?5W'8hzޜ~"jfՋw7Q;yik;v5~8~=>Al/_z]wCv=QOzZ++R%%rf/~(r/M[ <KK fρ.`xvY=pL䞘Bo#2!'K=Ά=h_ʶ_{X ӟ|Ωc{)+ yPbcn&?}yNN;'i8^E[35οG;Y=rz,X[V|c*Xi]F'AN9twYcGv AHhE=RTUUvc툩Sϕ.P9q9&|糝5󑽿|e;GX|5%Tَ-;rۑyrjsgWƏ/O 7~Ä@Q{,B< i]~|> endobj 14 0 obj << /Length 4258 /Filter /FlateDecode >> stream xZ]G߯8K{af X1vW#9E~}{~ܪFk;[^?!\~;k׿_ _}C%^o UqS^_k=mc=^wS׵>౮.ޚý.zOwo{^?{>Gb?ٿh䳰^o'z|n#/|{;˸ǿ=ޞl?"nn?Ҕ$ooQڭa$ēnȨ`}R ={z^?l8ILldݿ7?hm?'zz|=y߼?_?IM<Ϳ^۫^ L ? :i{p^ӘjZV/SSZ5R{]26S !1Իcs: vNNgj_zF7E``v6 /p'[yc#- wz Ӆ` [Py̿H~EAa; 8p$Ƒ|= {|=ޚ/&z3Wb 5Cŵ[g_V}`e&T_ώ/8?ܓ̚Œޫ}>$jN4Gwⲑ-`cVkJlR>`<3 ʹ FzF #GwD< IDGF< >2P,`6M0`3Z#LFXK03RQyTL{ :pz[tN83j±HQy&*Ń|>ጀm0Ra00*C¶7n$%O|ӯgcGb_xp{쿯W R=WJCxn7K=쒎x-fϠx/vǕ/ ʧ+ߊ𝏠$8bk |\b.>KF,^@x x }Y|U+sY5{--L6dɍKc;ߤZnt21vul;y(P Cd"AZ5%e(b~(ozT? `GbcN'EK{L{qnӞN{g7Ƕ- _qk3NEGG9 R4p4R<5Xe])bKQ3V\-J<TtR|z*Bc<%^GmE@jb^_E`?Kf#h෭h%crm-1(fTϖKg B"ŵ׏fC: |Ma!#ĝɚѮ;{_XC „w_"'2fg}xo`ejaw8` WRDXa&"ELVD٠PTd$Dv(F:5 1*iφX(Hxq:$iI mHH;=H2jb"_Iw/D 2")MZ"aARǒ0w*#D߄]HMH"^CnEo2Ql`|D"=N8i#(V. ](Hq$DBKvqQ袉hX5\ݓDS:qQAXOђh2D[}OI0E_T/čO8E$Z0LZ 6@`z<!ja_ZP4x!pCpIȇ„|xJvDnߨ ӈzTL#RR~Mm$È'. f<2~OdA\mG/%/ɫeb#jǓWڀXn:0&xkROb"!+|T '".a)D ̡4,aD'Np?b#/~25+76I0?e?%Mĝ:?Un\>EFk~9~DK{P ^k٣ M{aiOtػ Q_>n "tC`kׯxGΦx&:w<"|ȷnMnW3YPh?3߹Q69|!|">Y|#,L0l'_|&(\w4,go'_&1|[ִ.>&&_ӱ_%Z`/'PY!ɬ]v=֯s}#L8&nzH㮗w%Ǩ6'zN=OL=@ z^v ȉ٤৯݁8^ڭv6YnE y{%}XbG W3aQ8{4[8pOc &挠w1oy}\c==tڜlj9#!;acu;;NV~N/WEX6M=/pgX|!K9NTN>YX!?cC:vzPXM>#lf$"Ufp-3QN8e1$m3lbol'ن,^}E\2{ݮGye`1s1%̾j.yslkf4MN1)j3Sb{ ѢcjcF6K= Oe/pO3 I.Ӵ/ #it z eꞠKmN:۷:,廎9S)3KFQNb%|cDGo3~(FsXN:r(SH_juPfb? j"6L;83`+iक:1rW R 6TLxQXBА}&N hrZh CUf(op>eES;9**D3O/OP+a]O\ƫi@Y}6B]UʵA XR˞EČ/۟+_IxYaqm;Jà0x&f;]9;4c |d:s&b|dDYw:* 'Y||W+>S19NCxOTxY|U77?+b=xRv=ˮ7|F=]lG=w<ǝzI{* ]?-ݎzL*9vh{M,>xb6[zÈ@Q{,xoaP?Mz顑K/1Y2[oH#4z=Gc{?&zPz;7XQzS}|ߠLJ<{}s?]zz8狥ǫ}Sz~Ǐ޷T@5}K죟(֮vk 'NfUQ~ݲ"X&n)sngc#)?I7-WO}Ǘ߼|~/'_廿q endstream endobj 15 0 obj << /Type /Page /Parent 3 0 R /Contents 16 0 R /Resources 4 0 R >> endobj 16 0 obj << /Length 4257 /Filter /FlateDecode >> stream xZˮX߯8KX0ZD"$,qbd`ꞗ#و}o9/x}V4]J5YWO]/y'O=;p?/k ?}yC Nz1^zxw{5>1.*{Oo k|cwǂO>y~?v?OW;agaƽ^_\?c{{ "ow{s?R˯x4ظ?)%߮Ijn #0_tCz[r ~=oi1>xP `_owCx̐iqLp{8n,%=XtLE\iTOwxV^rzqBrG.,&lcT-/;=І뙍r7>8*Y=,bfqR0YN'r_,4c?qrkf/w~mry}4Wu0UB|LW$Ձ q# "Y|I/H8 BOJD I(AB7 gm79-F ,VdRCHKslCL1fq/o끻r8c>/0 XڅY{mO5Pń}`wo/n?Bo_?ZYb3s= I~\LXVf#Qm3޳eW/@Ě>l:c0& e37cp%͗giοo'O_0{z`'(G w>"GgwZ;Eϕ/mΧ+bM| ט(ϳ뙕éW?Dz^NL}L6z9P2}%穧迧[e3KԋKϩ{҃0<߿"Q=xCo2GYoC3/=du*rRTILWS`"tjE8qA= uwoMgKpa/#4ZY*T Ly*a6 Qo҃hS|5X)2S-hC[b4p BR8R X*djIԢNMpYJ#)@%tH,ܸ%uwb,MZe?Tßjv+~?S:Q^)Yj'ßbԹ?Ax?a ܟ= "gܟK1W ?:B0'7'`3~01?1U`>]?Qr4m6}0US91RcBrB|'^?ITNaZOHUF.IQ?QFO9:!57|xTKI A;.8>5YRK'`Ob_'?QW/+ß|N~OXG>@ σs}jFt{|Z5녆=ImܾӞ-}ArGk[.fZ__z۟ζ5G$Tm@ެxic/#Xc̐;^IϬ|P;/'߿;+ϰxp93| lO>Vo\k?1|Ml֪]az#nt81?1c;s#hKb̧e[Ĵĩ|n;} [O/sODTc~!yEY~WBFyزa?K{![S4ʴ/ dS$"sc<{mMlwbO=.k {=ݺ֋MGZ _,{X=n{;s?sEov'΢tX'o,?*Wa31ߕAH<+^hhoƓo*vpERTq;7_M>dZ|AдD7 J٤:L4Y_|KUŧx5%6)&_3O>W@|sr ?Pvgk#{w3_|HgjKګT٤-;k|b5fW~opC/ПxKOFz7d;S0^Q?^zhKw㩧?[$ꧩH$,Z^#CϑnGCjPiE ִ^z҈na=,֫?ۯ?`~?endstream endobj 17 0 obj << /Type /Page /Parent 3 0 R /Contents 18 0 R /Resources 4 0 R >> endobj 18 0 obj << /Length 4281 /Filter /FlateDecode >> stream xZM_GefHĖrqȆ`S=_ {fwvwo>r^UnK5]R[^ۿg!\> Z߇Ͼx}1wdžx3}ۇpbib +zzw~z=6{!"oww~H˯xzjq򧋔KS˟jGiO!K'zM%;)-,/? !Z|ǧWדo~W߽yLjj~W_^?(~A'Tջ#,W>gǜGT璱.r՛TTEI{jZ5R2jA2a@ڱ85d>``Fz~W!`%]ݵlwǹ{L2#+(y!.0ط11Q6_:-c;rc4sR{8 8rcX8`Xvrk9`xPa=p/6p$6%<(jĈvXeC`c(v#lFeQNi`]^08pnX61 mu'fox`8 {tg[gd5r>eOyLDƪckY~ڧq8ܨ /ܖc4>g[<0|94 p:kf8~kqޡ?d짂3a9-Z2dXMCĖQq^HDI#>+鏠' %K[dLx`FEI|@q>|a'/(Tsy 7O_47O_tޘB|i>9&IKp ||9_*; b~IpaZٙ7m06HsplDžJ<>09W؃f|T|\i؄m>0=͞l8#qZ|c=$sj y,{y^$= LXP#}^$t'0s7cpO~j|g]:jD%;7|#2#^(t/hjuخ|"N'sŇ%z_r-[>.Vfmk9v}QbEq||S\O|D\|UW>wrb%0ʧ}[l#XIG>F|{>Kd;حx^0D)?.=^o[ӿށj= )^&ԶXz ,=N~9?뉥zrIk=&z*zV0zWVs쭗Gץ?Kn"tTL'WʖҸ6}j+\ ū+^4X2]\e; JazYсQ8}{'.^{s,%J6SfU aI GGa{MyVe|Tӕh(f]C٨$e/MAqRRkkҦV 'r #I`Mԩ(r*t3T+‰S{bWO5K\&'+0sD)xhCjB*T{*ԽV*Q5Xv?8Jm8[^O^qj6=YzA,[K,eդbj~HGb6-Bwj2MTMzBi^約 A[P3u^=X)%YA)}XMzOf׫I2ϔ~q0j\oaXܟ7 }Z|d60%x20'#aneXrXbҁy>'gČySJ`#Pdmx$Lm<3U'+aS!M!ܟ诰g ßZ RK֥7Coe0Jvb`l_{xaßpPO/. -8ކ?I or, u?~&?!ޑ$L~RFTYuHPq??'Ks^߆?~~l>i_F<ɥ0'?B# eSRLd4ǫFgxD>ǸN~kQcO`6yEhF _'o\G._۟8ԏxfOt.dX\W&"=⹛?xO>@bu /Vo>~&_q6ID|H!/$nm 1|KÓO&Ak &?' ٚ/'Ė_Fc3j8gl|'H3Og$֣ȷv|LkG>﹟^ C/_;ݎχ: Ϗb7;CKr)駩0O=^s9^׌D S/6;'Xlm/IC"Ь5:*&fqY۩w*Yz==r.- vjEi}`kUO~jc 5s㻞'G5r k0/7.7{.qb3~߬+VEX*NS5/F"_E+;QңOfId !`4q"+NC综80^ )`H5j~VTu0'd$OdI٤:}ꎭL܆N3`Vxixb[D'q~]/tVџs$E77rST> GmŚ.MF$)0'FxBL!L/Juh# _4ǖH;ub~@,;~5lc>j`pd i֐N|DLeHPII/q#(_wpLeX)Ӂ55R<.4~xYhM~ya>mًѪeo>jq>KQy㼕_Q9E7eJ?jJÑ??+Bu $;hxxQqIŊoP1b^|||_oAG{gT\|X͇KF2Tŷ p}3nlsb6&k|@| b9_w!F`|dםl}G>Y|#rl||J#*qcy^҃ DzC/Г{75^zDﭦ^UqYc%ԻXmS/xi82'.ݭZzXf/E~x_zΗ42qg=QU%Yb'^VSRF8"X$R[[ =g-~>RҰ(.Xg/O/]?/?:?i_endstream endobj 19 0 obj << /Type /Page /Parent 3 0 R /Contents 20 0 R /Resources 4 0 R >> endobj 20 0 obj << /Length 753 /Filter /FlateDecode >> stream xVMOA ϯ·ww *P[&RJS@Ig<*B/l{9XuEm-l'p:SFcN)] +V vlD؀ QID|h sPp֣!|APDK/Uf}C%lTGJX (Xg{sc&+_S}17 Yѥh!hoHƉCK"81f1{NSbJORURCO7IcD -wܥ`) ShhѥhxTF<\FK L3K?ŗ-:5׀E#|GcߒyU/^[мm6]:lOo +hSݞw vgNIKƖmHxA@Ub/i #1y> endobj 22 0 obj << /Length 4239 /Filter /FlateDecode >> stream xZM^ ?.aۙk j+M. ) J$c!H hy3Ox}s}zUU/ztIwN׫g?oy㏯񗏮<B5_{|= #oC x/TMzq=z2w{ͽa{c[^ws;>c^?z:W>焈=|v7?=By{2n'G^~S۸.RV+.M%߮5ۣ[H̗nyc}<և~nqB+ɂ^ 9~gW݋^}w{Ͽ}t/?iݑ+ib΋sG>ǝտTcwWFJ0^.)Իcs:L ?zF"bf`v6L$^ N;8}FZA6(Nۇd0#vw_G+ R̖RÎq$_Ow_拯ջB+Gl͑xqժ}ЅmeΏ$f01z]x}#F؟Xld FQ5^6S[kV 0+#됭&s_ ?o*`Bt# *`y/v^oJ)3{Ή ,wt̙tFL9;2QRy>2P,>Mp`sZ#l`XKp3RQyTL{ :v4 plgOՄc;# q= I$8N8F(q gv# ma2$lzFR:Z~&<6(Sl |~7k6hm׫o?\cد硐>ϋ<lnOAa_+xA3oPHiA.JGl46MYA'`'QV켓r<%mU$X+8g] d m~(o~,Y;ytVx]مgݦ?ce&Ϫom[X g>$-}+:r(R44R<5Xe]C1!̏9j+R]ME%8]zROE|<#E Kq"Hv*u)ZY7mE ߶bАKPÌem8P,-%a B"֋Ǘ\Ma!OddMGot>?W66.LS%rsF5Mȇ?zx*&)L<>_S 0d%!#|p<q= %/ɫebF$vǓWڀr# ܬu$DOb"!+|T ǓX0 "tA͡4 @%L~\GQ:ףtmZ/:ju~XK<,{ Zkj2^mo MR$bxvog /'=_xˁGΦNv.6=v>P#_``;xc=[[/&|wnM L>,6h|&(\wt,go'_&L>e`ɷi]|L|~M>h^|OBeCY/hwDXzCh+g1qȮsR;Xm11mʌz_g==L=@;x~>o ˆ^Coпm=  MNc[OSgԭ|MkynzH< [/ԓH<97УHDWl"m6tz905C/?ˡɯm|DMHlCσϩއͦqGϫ_@Sݎ9m6:ynw nKVB;Dn--t=Ҧ9z4®>C Ҵ'Nc|ӧmplڜ[Q1 q==tڜisF6C7l}]l=8|:Oz;T73(wv;YA;.^mn&ctjkp;}3a]jFw:NUtûMی#mbHNo`VV͌\ nGo&a]8 gl?ƐD {FM(j_XlUMWuyIc+HT;f(#]߇V]lt_/پՉ4d:fϧS2)X; QNb%|cO|(/m4)_[')ne|QJLg||Q]dچig$L5JڴqpJ6rW R 6TLxQXBА}&N0b5h CUf(op>eES}sTE3"TgO/OP+a]OǍW`3@Y}6B]UʵA|.?iCnx&^ghwT&^F|dיW>+u{@s|1@P|#R6_~w*V{zejr{𭂿yY״Y'+U`|O;v9ꅭ]O oQ}+Qϸ=q笇{$tA ЋcғFDuMң:~2*SoKv Ʃn=>_,=^ =?~/XbDvu[l8q^-,e2vK?&oi+wHTQJ?}_ۯ䧏Nendstream endobj 23 0 obj << /Type /Page /Parent 3 0 R /Contents 24 0 R /Resources 4 0 R >> endobj 24 0 obj << /Length 4240 /Filter /FlateDecode >> stream xZK^ .aۙP[&R) JBI=Ǟ!H8s3Ox}}}zUU/ztIwNכ?׼ǷGO!\O>;>G>_?"/7Pn׫BUTדǻ-Xz)Z汮.<{5u7hSX<{{nq~ÿ޾ǿo~ {o+&F> ;z@ǟBy{/˝eߞ? v{oO >n_vrb_viJ,*Pm=J5|<6wևYʝ|=0[>NS [h%Ypo/w? !Z?R>xg߼͇_O?yx_ֆN{Pic#\piY[H5zzj]L[:6PLa _MKwHp\D Lچċ!ɖcgGoH 1}޵Ea3`6Pyڙבjp?T#mӝ?k;y.[s$^\A=zt_/,3tzv[ymGxy3.#O]_pF؉n~N\6X՚G/RfTόѕNؑuV9Z/[7fmFDt wFrn /j%b=ċcU:sɋ n&M/%ݶɈٹ )?G_wNō1"=Vw;1*ɃBV$Ycd(kqf!kg9pcl!o#[E J5NQs6ՀI1zWMjPHEA?`t W' ߰N O|7?^r#6`~ RO<]ҁbxݤxyv>f>|1_W>5XVL|%!;_WЕ(wuX5bE&ǃo[(훏@Tvp8VR;k-,ś"o[1h%aƲ6 Zb(fTϖKg0xjpzPUGצb'k2qg&G?+xh\V. _D&:; ۻ7YL-{[•I"}l."EA&ATfGT١4lت Q<h(Hxq:$iI mHH;=H2jjE$md5_"jep!)MZ"a O)IcI; p~bl.JI\$R~&$nnEo2Ql`|D"=N8i#(V. ](Hq$DBKvqQ袉h-j@' mMq)fu⢂6c9%efwmeI`S$͎')<T/O8E$xV-?x?aՆ Q RԒʰ㉎yc"$!&)9x&CLD|pM<ȇ&_j߯|x꒐iA>8Ȃ@/%/ɫebF$vǓWڀr# ܬu$DOb"!+|T ǓX0 "tA͡4 @%L~\GQ:ףtmZ/:ju~XK<,{ Zkj2^mo MR$bxvog /'=_xˁGΦNv.6=v>P#_``;xc=[[/&|wnM L>,6h|&(\wt,go'_&L>e`ɷi]|L|~M>h^|OBeCY/hwDXzCh+g1qȮsR;Xm11mʌz_g==L=@;x~>o ˆ^Coпm=  MNc[OSgԭ|MkynzH< [/ԓH<97УHDWl"m6tz905C/?ˡɯm|DMHlCσϩއͦqGϫ_@Sݎ9m6:ynw nSVB;Dn--t=Ҧ9z4®>C Ҵ'Nc|ӧmplڜ[Q1 q==tڜisF6C7l}]l=8|:Oz;T73(wv;YA;.^mn&ctjkp;}3a]jFw:NUtûMی#mbHNo`VV͌\ nGo&a]8 gl?ƐD {FM(j_XlUMWuyIc+HT;f(#]߇V]lt_/پՉ4d:fϧS2)X; QNb%|cO|(/m4)_[')ne|QJLg||Q]dچig$L5JڴqpJ6rW R 6TLxQXBА}&N0b5h CUf(op>eES}sTE3"TgO/OP+a]OǍW`3@Y}6B]UʵA|.?iCnx&^ghwT&^F|dיW>+u{@s|1@P|7*GqlR)~3T/>KUS[|"ۓiO>Wv>r [Oe>QWqz;Yy~[gQOޮnG=fbnp*O[Y8-e.6MnW?2~#FRG(E~_};O*Pendstream endobj 25 0 obj << /Type /Page /Parent 3 0 R /Contents 26 0 R /Resources 4 0 R >> endobj 26 0 obj << /Length 4243 /Filter /FlateDecode >> stream xZ]߯8KXdf%PR81MTu c$^ s3=sn>+;UV4]%59]o_^/]?y;p>ך=> ׿}C%^ UqS^^O~41};)~^oM{w k|c=pc=}=}Nرbٿh0^^O~=g "oww'n/!m.RV+.M%]%jGi'ݐyg|R =?xz?LXILjbٿ}7oxhm?J/}7~~==Ljl_<[:CtBU;r%S#Kmlӊ?{HտETcwW&J^v ƔEw nꘜSAᦓ>棑䆸 Ln!/p'yc, wz s 0g%vwG+" R QGb,ӝ0?n[Dw],Rߕco-xqFժ}0ٱ2b$f0q'pDZG2/V#pb_>zMl`ZQP3lj 3`J:d"N ylZa"Q!:lCV$_dCŜsEnc9syqs:z{X"mxoI|QF|E$Nɷ4_/9Bxp/nda/X,zPI)`EU2{;Z\YȀƍvpɵ3ϜA1h~طdP!`t+*w3T O]$x @HDGFr=$[ˌ` E(qPʘ&a(~-OX"TTޟ" 9!ਗ਼lW!pDCJe20e" 3qFeHVƉ$C׺Z~&<~)6i>5'$9-z5b2}s>YYss(ȎpKGUxBB= x<_ (m>@;ŗ\'A\GK:Z,ϐ[`uSQSo|GH6bk |\b.=JF,^x t }YzU+sYx--~L5bɉCKc[ߔZNt*1v ul;u(3P d"Z5%e(b~(ozT?Ώ`GbǬ\O:J+ xxqn3xSgշm~hqpHQ=_M3O VY#"?pLxrTW#cFbx\D#d>8Q8rwlv R;k-Y7mG A߶cѐPƲ6 Zf,dUϖgjPMhjz n>a4vSjA3! t`\Χd K04!b|`'m򩘉G>0|m$U|HD6'lZ򢑼Z&>0';&ʉ$hց/(IJ]LBBW'".a%B(R'D0 n"r|Op?bա >X܄p|R OOMq>Q"ҧʉ O}D`|~z':_>R ^>^t^7u?H t/?@AXKX&l5~<\~H< /H<9LoG˯"D.?m]NHL,oy0בتO/̦qՏWluӗ@SVB;dm--zڋ%fyht~bg29Jgߞ81;̧OltЏyFPo1 FQcu|gd3=yyb+}?/vJ^lUMڈWu{f|ILWwP~þs>@'蒼g;Lr[H,]9) -Kh'1m׋;qO~(£_h)_['i2D? Vo&\=q.2mę#C/xw%mb,R'PxJa_ǿz"/JzQ(c?4LX/ðվ(?Oczѹp)fzzLzq׋fS%z1`=pe"뉑yx> vƿÅ(kףюPzv-xC/V'qo:buq׽+{_I,,>iDX|#mQ̟Wa0>|d+_ho&+4Ǩ(u&•Jwsy|1@Pz7*GJzRg*fGީX_z顗Ɨ[~s}S"SY+]`zOz@\zaizqԨGgq笇\?[gdQOޮnG=~Uts/ۡY5ٯ0~~|b6-maBۏ{,B70_蟦QX嗘O~($OӏQHlFʇޱ~B?A~Q},_~҄n~|ߠLJ<{}s?]~~q᧫oˏWz}Ϗ-o8j~ G?Q]y#NīTeEL@Rngc=s~(,7o$aRO}</>wU,endstream endobj 27 0 obj << /Type /Page /Parent 3 0 R /Contents 28 0 R /Resources 4 0 R >> endobj 28 0 obj << /Length 4366 /Filter /FlateDecode >> stream xZMG?b!鞯k ElCC >UeMCݙ驮x}~/_A*Q.z=/z|ųGC_˯pw >|-z5&TMzy=x2w{=^0qw=1iE1ws c=}Opblb⿟/,#|n#6S~{;˸gOq.RV_.M%gWIoo{(0$jf)w0[\%;)-,7/ÛH_)_xo~x돿~~/~7kA'ӽz(~áTջ#,Wоe΋sQKb-Rީ^)l7f !1wWtX9)[i[TD_9A8xz{b$t>ZDtD$C(`b Fi#dadZ`bAawAgm;#x&ldIeO"Axp6B6m8# 36 %.3 !aY F 'NkXgԣxLqPxp-W~2&c끝X>8lnOAa_<;u6Kt\GK:ZϠώ،/ 늧+ފ$Ďt38$x]|bX|Q=#.>R#V2jZt[0lhdɅKcߤZ.t217vul;y(Q; І\I3rm@6.;AіߏF[QH1s'+";1_\g;`v^qkg>$ZVo{ /y^ O z^Mx&:7]m{ x`Gvo,&h|&H\wt,g/'_&L>pɷh]|L|̓e|.р6$3_06g>"xWτmmixuoi[cc֔_g>=zvL[/p|5ޠcz+cZc~1XPދT#cVt!f5i_ac$ PA|y}ȁlyOP%yzLt]HNAGNp%bm$|QWv>r O;e>Q#}+[ߑϸ~=v̇?ۭ3__ȧDo׏|K#> endobj 30 0 obj << /Length 4262 /Filter /FlateDecode >> stream xZKbUڂH(Dl) Ă&؈S/V a[gO:U37wϮW[ҨwMxt~vzŋ?>yw:>/kqx}<"/b(P7gn<Ƴޡq7x {]<ƵEx=w k|xOwo{=>6<Ǐt7o^=>C‰=銉?_4YXqӗz<~^wGl~],_>{+fO >n_>H[믘]K~/]%j٣[̗n0K'zs{\c'1VW߾mb?+g<߾0ث믟zZt/_i+hd΋sQ]jbV!yToRM9c@cE-TTV`xad,0|0Bc0S0r2T7Sx&|4 3C;r`ñ3#طxl>^Zay`{x0%vwG+ R6H5;Ɩ|< x5_&x3Wb gkĵԳW>pJ4Cg/?'7W}<}g c D7x4٘G/RfT˄0'DW:aG!Mhl~T#F-dQ^&)jwSxqr1 @ǜO7yqᩛ5vGuE bX"m$gf(##[&c = 4D{vbT !XdՏ k&3!g" p!r3Gn-2-~pbAi"lyP0|\@xzD#bpaw p>@h1G2@E2ҧ n`^˓1z- k npF@(*σzU9!࡚mg!'qac?D e|>ጀδ`6`0lde5o\HJ268ӯgc`S1A wӿf %0Fl^ xyȘ皏Q|vcjRkB/ _п*?AM?9/x'l>7?^r#6`~ RO<]ҁbxݤx~v̇ "3Wk[/GkgԕpseuXD@3Yi#uOg^{}Y\ 'R"ßu {~EKW\)d}KJǮPMjaFf#p.ڄNRk"GkUjv4?&3QQMÆ#b{B  SQBfTЖJ8Ș:@KQn!Mٔc8EK#%U,4xTx6a$.)mRKihr[I֛Lj0&[/8&6Q1uvmjSQ5KKG S15KI[*8R}wjah%TT[ot) [ʖ:݃I8K=qAOтhI5I2ā'ؔNpR0kz^/ZƯ~A<67Ն?)fŚ$ٍ?y%xޙ]xZx7ؽxdk7)haE<667#޺;`+^91gƳ ѐfs,}'f`wxkg01|Dǰ4|EgE>|Gǒ&JR}%mS |+JǴm9?usڪ;s<hǴM=AY+l 7Gx>m~\zMNc[OhSgԭ|k|'znxA/L^ă˩'xroʡGK"YZ.=۬.rajl^&CO_ۡx< 6KݥتSO/7WRms,uӻjn%n<",MamcE'b H0a'>桰Mi ]bIig?8m:ezvPfDJlf??D<43B5&n[8mfEeAZV/P_n'KJm'"q֫KD{R-؏ ng#X"VHݩ՝ѷItBd IICjXԞhV!l#ɰˢd4T$[ch޴Ḥ_#yn~dk2IzRb"I?%nQlՊ`&5:41kdq_M/ކt\MO|,Һb">WslQGRT{\IHu҆4 H_A)BCQQ ٲv򤟭NQI<{=]/⃢^G?T&kے7L,dy >an@2ۍI։wX2ED@|Q-;JW\>qVD2lô39/ J66NZ\yJ!j>i/Jm|QHi<4LY /ޯ(_Oc|ѹqef'||ь|qfT%z2`=@XF`qU|}Z7ޏFk*E\ XR˟nKznE"~zDd5W>E{$tA EЋғFDuMң:Wzxѥwp7}r&롧[oKW{z-o_@5} 죞(V"l| z9gUY,>p ^)#.Ŀ `-E~Oe|e?R"?~_k~i㿆Eendstream endobj 31 0 obj << /Type /Page /Parent 3 0 R /Contents 32 0 R /Resources 4 0 R >> endobj 32 0 obj << /Length 4266 /Filter /FlateDecode >> stream xZK^ .aۙP[&RMS JBI=ǞWBPy-q>fc/^\r^ϯ_xo<B?|Wk}~럏x}~D^poㅪ\/'?Xw[汞}S׵>c]]tyzknu|ևyts8GOy<{"_OWLw?|v׏?<#(|{;˸= ޞ|?"nnҔXU~{vkxm5;z_a[>NS [h%Ypo͛/w? !Z?R>xWϾy?~&5{7˯^}lmd_iݑ+i2O~sYO_C1;իU#%/v ƔFw fձ9&vNf Nj_zF"bf`v6L$^ N;8}FZA6(!ۇd0K TW-wiH1<o_}=ܙϫw1O~Wޏؚ# ׫U8za ׳h/8?“̛`U_Owabc5NtGwⲑ-"E;_5C!}y/_ß PæV<;g+AR`)ֈ+oo>QEwɆ,|pilbTˍN&Ny'y:JtWHбVpF Ce(wQhQ?*Yi3v<(x*F1D#P[HTRo6ۊ@m !_˖`7lkqYR=[R/!͇KW♫EPõhx1.Fyl]+W.l^ /3c;mxdZOܙ59{~܀u~;?4v/+Wh/|r^lzJ=2>%lcW&"vŚ8JmBQҚFUMOIbTTӰ""2DQl@a#ŅTPY*&U&l%RN!TkiPscԨ~1zHSeiJA?! 0f?`V cvJґ !t{ @()~I d&J1M͂tPD.~tSBw&jJv^rKEFRQ۰lJ=YhO1qP-T3+~pR8 nvSZ"쎧h50iyVm @ Oh/.i `8<>&M!qaB>8,È7jlB>4@!OS1i|Ha "Iȇ'9 &,xOZR&V>lOBwk~~DKP ^k MOJt Q#^In "tdv6 o{9ȉՉnRteƻ'x lloGuk v>vV䟙ςBC΍|@'⣝7txm& `K|([ɗ?ODkeӦ&_3_%ӆPYd ]v=֯Gv=pxv-!wV=-mzLF5^Yiz3>SЎiϛzQol[0>mA?.=xS>CS:Fqu-;z{kz[`c_=֋xp9$OтM9(zzU$"[˥gFN=Drik;v'?f:[sa\@jclN~l|}۫X061&/b"HMpai3(SaWؼC@RiكMMN>6 H$٦yB D o!c Ny}6i3iĦ{߃Z8$n7Ix9Bg%䶓@LHf=FOrz,>Vf$NN>ۤZc!Jц$y֡um5Q ,|IHjv4P!셣p˦d T$`h޴Ic^#ynydIJHzQr&Ec>%n6Q՚` 6:41kYdVҦQOjCMMӦ'}lҺDTcB/>S٢3uʋϑX Ui4濂DS2QQx}lP;y6x("HAQcN|>QbcEf/J6Q@&~nXd:&6QH()_TR 8_Tk"aڙ9/8 6mR "!m.CT// |"^(4dF<4LY /վ(?Oc|ypf'||ь|qfT%z1`=DXFbqU4@Y}6n]UA|.?i/I؄x&^ghwT&^\|dיW>+|@s1@P|7*G!lR)~3 )|ŧ &'Hl'_f=|Ti=|v=ˮ7| F=]lG=w<zI* ]?-ݎzxə*9&i{M  ^ M=axK[o#ӐWw` ;x)㏺i1I_s;6Shҡ57yC/jKOխ7ՇKԫdOݿ.Kwӗ[/wzZxo[ww`}ŚׄH9Ź^N{ՙk¬7a 0_ o&)?5+K}W? 1)[Oן_Z~ϻendstream endobj 33 0 obj << /Type /Page /Parent 3 0 R /Contents 34 0 R /Resources 4 0 R >> endobj 34 0 obj << /Length 4244 /Filter /FlateDecode >> stream xZK_ >]¢3ck j+M. HS {=/Bx-Jnj}||'W}|z}{~ܪFk;k^'pO>;>G>~D^poWㅪ\/'?Zw[汞}S׵>c]]tyzknu|ևyts8GO}>{"OWL_4YqWz_?8~],_`_6no)w+v{oĒ߮5ۣ[HWnyg}<և~nqB+ɂo~ 9~g|7o_<7o>z{|W/^x6t2ݫ88tzwJ'?9Vp_B1;իU#%/v ƔFw fձ9&vNf Nj=W# r130Uzk&/p'[yc#- wz UC2CqhgC#)fqaG8;a [D_w]Sߕ#HvzjN^XfB2Gxy3.#O]_pF؉n~N\6X՚G/RfTόѕNؑuV9Z/[7fmFDt wFrn /j%b=ċcU:sɋ n&M/%ݶɈٹ )?G_wNō1"=Vw;1*ɃBV$Ycd(kqf!kg9pcl!o#[E J5N?hm׫o?\cد硐>ϋ<lnOAa_+xA3oPHiA.JGl46MYA'`'QV켓r<%mU$X+8g] d m~(o~,Y;ytVx]مgݦ?ce&Ϫom[X g>$-}+:r(R44R<5Xe]C1!̏9j+R]ME%8]zROE|<#E Kq"Hv*u)ZY7mE ߶bАKPÌem8P,-%a B"Ǘ\Ma!OddMG^pu+xh\Vp)?%;;,?}M{/S ^Vp%%mk_7[ Hf+lPl(Ud$Dv(F:5 ."*i, ^\N: EEabF[24N`LZ w/DlZ`HJ`HBJRX&N\eR_ IkhFLTh&/$E5QtHvObEH$qEꤤ- RE; QP;]\7hb7چ-e.PDBDSxEXhIDD[}ā'Ipj/k~~DKP ^k MOt Q#^>n "t v6 o{9ԉnsƻ'x lloGukv>vV䟙ςBC΍ɝ|@C1'C7t&xm6|0%L>MKɧ ?V5i_X֯ ؋iCz@`pH2.Qohs}#zEL8&nv^wz =F=mCQ~UwhǴM=Ak 7G޶^aaשw q!)C7_zO=ֽ [z_?O=-[dEZtM1#؎uՏɥ^|gvO3 I./#it z eģꞠKmN:۷:,]njT}J&kǒ7IldyOE8zPvc9k;?mL9"Q~/A㛉,׃O/L0ߑ]I6NZ\xJ!_Ն>i/J|QHi#\aȿjLe ΧLqhF >8 TE3j0ve"i#1}lƿÃ(kvϣFJ?h/'u;+;޴ہ_I,,S19NCxOT5,>UMnU77?+b=6s Li.G_vm5ꑽze;G8uKTQQovcƃ̬׌W]_Ck_-=`8vm [zÈ@Q{,B7S0_QXߥSOԭH$OSHlFʇ#߱zD=AzQ},_z҈n>XzToP^={}s?]zz8狥ǫ}SzǏ޷T@5}K죟(֮vk 'NjګTeELýRngc=s~(,7o$aRO}</>w&W endstream endobj 35 0 obj << /Type /Page /Parent 3 0 R /Contents 36 0 R /Resources 4 0 R >> endobj 36 0 obj << /Length 4283 /Filter /FlateDecode >> stream xZ^Oqaf%PR!1!؈~fcCX99_>+;UV4]%59]]E^_<Ǐt믾}|{O+&w/,̸oj#].wq/{I˯x{jq򷋔KSrooWIooQڭa$KI7$k;xŸ{sǔZ)g?|wHȁ>z^|/ä&.`篾~քN{PNwGZ}΋rY]jdVYE5SSZ5QdL0|(Bc0wWt@̜ 7?zF"b00Uz"Hyc, wz s 0gC#)Ɓ#1Nk;y.HvzjA>^XfBXy1=ɢfܽ wq'+a~\4l,QjͣF)BFZU6όb(]#됍& "^68!n*`iFDrpFr[m|1sΉcQ:u:ŅnsE" cdM2%};GA8%|k =:`#`CDa'G @%IV}ˠf*(kqe!7%ኀm(RKf!aZ' E_kXW`Q<8An0& Ոx1g=fzh"ϡ ;-U9 !70#_0O`>7`<_re 6[?q'.ko>CnR<^l=;+_ @וOEM=V;!I؈+ghq;D*zE\z7-G*gUṰg.`1^t%'-Ml}Sj9qVЩ\)Ա[q2@*@ kgbrT ]%Q8?:Yvr=(\/*/! 3Ϻxƺ:MU6mS`g~RpoN#FG9 |9l4r<5Xe]1aQ v\-J<q:r9>x:FG 0q"߱QۑHtr g9l·1}ێDC.C ˶P7LkqYV=[R/#- C"֋o4'" }3! fLM;,w&k>~«#[8{~u~;?4v.+WAϾ= ?}Ŧݭ׻;.9d4}XK`e`WSZXafEL*`W&jDR G3Sj540BDUnϨ60Ըqu)J(,S*&ڒIIyPzjm56_h֔2tP Wƴhè (f?`V &Rĭ#Ci@QR&, GMb,SmCJѭBRLRҶ )R]ah}3z9nJGmKV{O1X(|D˪fʼNif=`|VT/č'L|VCHGȇ&_:"y||iA>8%/%khb#*knr@Hbk;ZuI:$yZ|+>Q!TV!:xy\ŭ'HZJw-/}`GF ''|be $/[#u OE>V`q+zP g?ĩxc>6~Bxc^׊Gj#~3w3ϿB]bO즟{!>t?]|~->Ayp/ybu|v["|ȷnn=W3YPh?39QSyT0Bxwaa:ako ˎ†`|c~+?g;Ə8_~O?ֽ5[~DO?mcc_?xp9$OӛrQ$"HD6;~905/S?᧩m|ZVwu$\@/nDZ91[ws=vǫ\06A1&/b"H0I|ڋ%H \;d "&ξiqbmz8PH3H"=&mb'HMw?Rql?"<P]xqx]qf%;_b&38FjW<{(2>6iݎLTc~B/~^Mguʋ#Inӌ/#i O؏zz]߇IV l4^ij}i~E~8O'>U?QbeMfC/J6SDM(FsXd:&($@HC/UGCO\/5L0qoN  J ԉ!$-7AeeEHۺ^  DV0La+φ2X^t.\yv`I^4Bhzb*)U^ 5\zb$z'^uO}XB@5_[XhǭkJv<+^yœ7I&t1:Oe╽/*_B4Z",׶Hd+°L&x]ypw>hC/ 47IϕoGn:U g;߹<ԘzbZzAbl=Qc鍊S^~虊ԥw`֔O=KUSxB ĬSϕ.0m'G= .G_vj#{w3_ztC^2^Bo׏zxs?z*9MҬH?@>~0!GOC_!{g/O^~hKwL?[($M_~QOGIԠ >/?iBTT?X~TU_%ߓ>u>n.?_n՚Gǫ}~߷_@5K죟(&l@)rUg~ ~#X~` Sfo݄Mxw4aXƯ,_Y,hn ?y/_\z?ktendstream endobj 37 0 obj << /Type /Page /Parent 3 0 R /Contents 38 0 R /Resources 4 0 R >> endobj 38 0 obj << /Length 4290 /Filter /FlateDecode >> stream xZM_GsF"T*@llB~ge~vhgv~r^5ݪF\;/z!\?;Zx}?>D^pCS^rfk5?,I@J<7߾o@ z'ѳo?O?zŇMp{5>WϟLA ? :a-8/~ayDu.)]E&Ua@yۯV jZ1 1]=1^ܱ8Q.:F8߭F.XèWowmqlu8elHUAD1}}ݝ 1̐b2A?&qzx^ &D8#𫘅ftt9._|.}OxL3\JdzXnW1&k?x k43w>1RA:΃r*2 Uu'fcS-;8X-ܟp s O܏ %a 18"y /":Wf8Y3%Gdt`V9y}|#&! HwTsy E' ^/dB'\8Q'Kb|Ai|R ZOB 0 9_q?D8 h>n%8f `X/I !-q_p 3K``k:z"xpz˹^`vʱ_ =RKk۞j| _6ϋ 3.֓ρamǝ/%O8P||D\|ϲ%ڝv>ăȟ+_f;ȝOVX㑯P;g3+S`#\ <~l0mlzdl| sleKSOOˮg^aS?iϥax>Eƣz*d_zx^zZce4ii`wmt8 fIuaB^T']Ѕ.Ԅ* /EUjQu*.,m2+Lӧ?! P_Z ظ ff.0#*Rlf+sgƭ #KfJrF&1C302Ee* L*(f Ɯ'qL-{yPm`7pbpg4M7sJ\@yP2 P)38? ącdJQ2)u J&1 a ܟ< I͑ "D~ZD%RJ}`OdkO|>Zg`a:wbfzrxq%h' dagnbd„LN~Ze'ԑ 2SrB&n2&6)[edp? q87Xq|K$͕ OĂM'O~%^ W߇?9N~nO8XG>@ 86?!q{jFt{o퇒\BՔW niܾ v9ϣY -y~wNf/*O:eߚ-l#I*6dlF Y|LoVIx`G1 o,xlf͔gdwN> x /N>B"de/\gX<|O'v+7pc` |Ml֙]az#t8119ƑhKb̧e[Ĵĩ|n;} [Oz8C,CI zQ=St-s*kw^?O,_m=ȖC;"Di|sQ+WH[VޭIYzN'穧ɯqtux]&s~5zw D5=9 /Xr!~I_3o~L͗Ssu"šC͉3+6ZkїưXD܈%Ӧ&Smh bv'$NL۰(RWŤc45w||MWXo#|WgLo+IbeMձ%з<1^ r:a'G9)X)Dܘ<5qϳjݍT-fqͱwcm9X _9vNK9-2Ť.[=)c Ҧama0cRs$v3aflmUs C쉉!fNMnSb9::G1/utNL?j6eitq-%Ccuq<1k.v?;\ZBOz룆 {"\wr<5ΤSǖRV ɘP}a$q|~ԐS&F&|a5O8 C#KcpGUh` >|avKTOE_4#Bh|Ti/04Eul]O\qUz8Zm,h/23iك|c$.ͯFX "S@\8k/c#˟߮/#f;Q6ma?0]ن;ijⅆf<\bV<3^U#b=xA[lt MOY|?HqWgF\|C~ԧ_,>UǃoUǶ1xR{o3g> .Gdo8?{X3W#qz;5̇?{P3_^ȧlnG>yXpkkuݟ^?@-=a&[o#͎W!O=x~zG5C#~^b3O=eQ"P?M=F"aM:+z|t=zPJS/jғFDuM mУʚ7mJ̷Kv[v4wnrnm=m¡ǫpKw|o_k]T^w.(<ߣ=ʴJja|o2 ,E Ք~W@ec/zp?׾~58o'o' ہ"O!?~?߾p} Ͼ9sendstream endobj 39 0 obj << /Type /Page /Parent 3 0 R /Contents 40 0 R /Resources 4 0 R >> endobj 40 0 obj << /Length 753 /Filter /FlateDecode >> stream xVMOA ϯ·ww *P[&RJS@Ig<*B/l{9XuEm-l'p:SFcN)] +V vlD؀ QID|h sPp֣!|APDK/Uf}C%lTGJX (Xg{sc&+_S}17 Yѥh!hoHƉCK"81f1{NSbJORURCO7IcD -wܥ`) ShhѥhxTF<\FK L3K?ŗ-:5׀E#|GcߒyU/^[мm6]:lOo +hSݞw vgNIKƖmHxA@Ub/i #1y> endobj 42 0 obj << /Length 4240 /Filter /FlateDecode >> stream xZK^ .aۙP[&R) JBI=Ǟ!H8s3Ox}}}zUU/ztIwNכ?׼ǷGO!\O>;>G>_?"/7Pn׫BUTדǻ-Xz)Z汮.<{5u7hSX<{{nq~ÿ޾ǿo~ {o+&F> ;z@ǟBy{/˝eߞ? v{oO >n_vrb_viJ,*Pm=J5|<6wևYʝ|=0[>NS [h%Ypo/w? !Z?R>xg߼͇_O?yx_ֆN{Pic#\piY[H5zzj]L[:6PLa _MKwHp\D Lچċ!ɖcgGoH 1}޵Ea3`6Pyڙבjp?T#mӝ?k;y.[s$^\A=zt_/,3tzv[ymGxy3.#O]_pF؉n~N\6X՚G/RfTόѕNؑuV9Z/[7fmFDt wFrn /j%b=ċcU:sɋ n&M/%ݶɈٹ )?G_wNō1"=Vw;1*ɃBV$Ycd(kqf!kg9pcl!o#[E J5NQs6ՀI1zWMjPHEA?`t W' ߰N O|7?^r#6`~ RO<]ҁbxݤxyv>f>|1_W>5XVL|%!;_WЕ(wuX5bE&ǃo[(훏@Tvp8VR;k-,ś"o[1h%aƲ6 Zb(fTϖKg0xjpzPUGצb'k2qg&G?+xh\V. _D&:; ۻ7YL-{[•I"}l."EA&ATfGT١4lت Q<h(Hxq:$iI mHH;=H2jjE$md5_"jep!)MZ"a O)IcI; p~bl.JI\$R~&$nnEo2Ql`|D"=N8i#(V. ](Hq$DBKvqQ袉h-j@' mMq)fu⢂6c9%efwmeI`S$͎')<T/O8E$xV-?x?aՆ Q RԒʰ㉎yc"$!&)9x&CLD|pM<ȇ&_j߯|x꒐iA>8Ȃ@/%/ɫebF$vǓWڀr# ܬu$DOb"!+|T ǓX0 "tA͡4 @%L~\GQ:ףtmZ/:ju~XK<,{ Zkj2^mo MR$bxvog /'=_xˁGΦNv.6=v>P#_``;xc=[[/&|wnM L>,6h|&(\wt,go'_&L>e`ɷi]|L|~M>h^|OBeCY/hwDXzCh+g1qȮsR;Xm11mʌz_g==L=@;x~>o ˆ^Coпm=  MNc[OSgԭ|MkynzH< [/ԓH<97УHDWl"m6tz905C/?ˡɯm|DMHlCσϩއͦqGϫ_@Sݎ9m6:ynw nSVB;Dn--t=Ҧ9z4®>C Ҵ'Nc|ӧmplڜ[Q1 q==tڜisF6C7l}]l=8|:Oz;T73(wv;YA;.^mn&ctjkp;}3a]jFw:NUtûMی#mbHNo`VV͌\ nGo&a]8 gl?ƐD {FM(j_XlUMWuyIc+HT;f(#]߇V]lt_/پՉ4d:fϧS2)X; QNb%|cO|(/m4)_[')ne|QJLg||Q]dچig$L5JڴqpJ6rW R 6TLxQXBА}&N0b5h CUf(op>eES}sTE3"TgO/OP+a]OǍW`3@Y}6B]UʵA|.?iCnx&^ghwT&^F|dיW>+u{@s|1@P|7*GqlR)~3T/>KUS[|"ۓiO>Wv>r [Oe>QWqz;Yy~[gQOޮnG=fbnp*O[Y8-e.6MnW?2~#FRG(E~_};O*Pendstream endobj 43 0 obj << /Type /Page /Parent 3 0 R /Contents 44 0 R /Resources 4 0 R >> endobj 44 0 obj << /Length 777 /Filter /FlateDecode >> stream xVMo0 WCrږ-6K,R$(Y vi/I>$ g`9<@kyhQw|gu`pd6@}|SNK0S8Sĭ,;W: a6-x Lpdww.cY V=@4=y_endstream endobj 45 0 obj << /Type /Page /Parent 3 0 R /Contents 46 0 R /Resources 4 0 R >> endobj 46 0 obj << /Length 4271 /Filter /FlateDecode >> stream xZK^G .X^fƞ׶*@*ĢbACTIK}αՐHMˢiW{|q}w~ܪFk;͋/7go>B?Oך<?9yLJ!rK^rz2w{ͽa{c[^ws;>c^?{6{7_.!bat??ٿh䳰^g'zOg_?~8>.wqǿ=3ޞ|vrbןviJ,vDFbtD;,Nc}{G\-')-,/w? !Z\)_O^y}_gIM</7/ L ?:MU;r%yӟƜGV+ӲjLNjH & %c1廀z|ulN 櫑*ݵ C-<`b뱑b;zk f!m83C#)fqaG8;a [D_w]Sߕ#HvzjN^XfB2 Ώ$f01z]x}#F؟Xld FQ5^6S[kV 0+#됭&s_ ?o*`Bt# *`y/v^oJ)3{Ή ,wt̙tFL9;2QRy>2P,>Mp`sZ#l`XKp3RQyTL{ :v4 plgOՄc;# q= I$8N8F(q gv# ma2$lzFR:Z~&<6(Sl |~7k6?hm׫o?\cد硐>ϋ<lnOAa_+xA3oPHiA.JGl46MYA'`'QV켓r<%mU$X+8g] d m~(o~,Y;ytVx]مgݦ?ce&Ϫom[X g>$-}+:r(R44R<5Xe]C1!̏9j+R]ME%8]zROE|<#E Kq"Hv*u)ZY7mE ߶bАKPÌem8P,-%a B"֫W\Ma!OddMghם=lxNj㡅{sYa»/|r^7ldJ20;5l WR&uЊm"ņRMORIdbSӰ"b2Fl ŅꤓPY&)&l%#M# Tki pMH~&zP_ 6iъ&':A>|:l\dK0j1 <6TL#Rx}|6aɪKB>Gx" zhh$PO^]kʍ$pa_`rǓXD"OuؿL~b)zDSi' [\=^~dcjpj<b-Ohuzx-67I7S;$zċG<ٍ?wAcOͦp&ѱɇ)|I3'Ju1mk55\{=mU Ifea: mzDYhף m;"qK`S[ҶǨǴm(35O~?3혶^'/z Aƶ+37:#n=D^z6T=~Mu;٤৯݁*ʇڭv6Mn"B^/oK f2:J8m:wvOcA?isFP6oyfF(myksLAް}lEv<P\_ΠdYR.zhrK63br*3 꿙xu('ѲC6]6mol'ن,^}E\2ݮGy%0y9 G[_v弹mkf4MNmSf%7ԓGnSUӴ>f|۱n~1؟PދϠT}cUr!V5i_ac$ QAxC3^v}r [tI^޳ )\gV'|E|P똑?qh&?UC îLu=m$z7^uO~xey4uW)m<^]ta9AxuSxeǛv;+q' okxT$2g╎AaXxvw]9;4c |d:s&"^gj2"\q;{ Ce_ߨ')ǕJTL.S?Ӄ/U /OUۃoM>ϊnOz<\{Q/l=zb]o|Gzd^zQx>;g=9njG=Uz~[`;35UtsƗЬWEK>@<]z0"ЭGK 3ꧩw?V/=4w%;Su- c$&[wl#ѤCjPo^`˗4"[o/Wio^\zOp/^6N=tvpbjԶ^񣠥7G?PM~'?odÉ(j p[\[X7yO_a?Kk\|)\_=/_}o.?֘H?~/W^|endstream endobj 47 0 obj << /Type /Page /Parent 3 0 R /Contents 48 0 R /Resources 4 0 R >> endobj 48 0 obj << /Length 762 /Filter /FlateDecode >> stream xVMO@ﯘ#^_Aj+Dq@K13%~y pAF;q'l)͔i_uu ~)r+MN;AmzX n ^'b8,)%SukjV.0{a> endobj 50 0 obj << /Length 4250 /Filter /FlateDecode >> stream xZK^ .aڂJD Ҕ%<D~ϱ BW{|r}w~ܪFk;_׼'p'Zǧ]#^㿯\b(x*n*ݖygCnuX~nޚ{]4)a=ݽu78\?go7Ͼ~|𗄈=E#z=}uw~zO!=org'n/mo)w+v{ oĒoWIooQڭa$+IId}zs{$1Vw߼mrO+߼xo^_0ػ/_|táTջ#-WȜ?uyd ?-TTV`"0]26S !1wWt9) :ૉn n]0x1;r-i!׻Vؠ:ll*C;/1:R_nbGjv#zz5_|Mpg><]y?bkċk7g_V}e.T_n+/O2oW}=݅;:bI ;/߉F0`Z^`3ljQ! ;j2G+eB -ԈH7nΨ [vb7MV[_́2Sxqr @ǜyN7yqas"sⅱD6ޒ>3;W8%k =:ñ@CDn'F@@%yP$2{Cb-,D@zc!ʹ ƈzF#cH;|8 pH`#cQ 2^P7 F0wQ=–78# HD\owKΐ vFTM83ד8ʰqDJc2l>pF@jgm0RKf6*C¶7n$%O|ӯgc`S1A wӿf 3J`}P1>fYI} s0Az6/x6 )m<;υ\鈍'حxdt൘7A7)x/v+_@@וOE=V;AIt38$|]|bX|Q".>J#ϳV2jZt[0lh/:Ȓ&vI8+db$؊w8QDw kg<,1Ql]v-q/>卶Տő61k'ϓ"0_gY-mWܚ̇`o@S Q=_XKr(&U1GmU+آC+^/Pb({)N;)NŚ.E `1>Kf#4Vu jl vö %ճ%|d>L@|5@(Z5\zb6psՑ)b dɚLܙ Ogʆz=Zח&)?%;;,?}M{/S ^Vp%%mk_7[ Hf+lPl(Ud$Dv(F:5 ."*i, ^\N: EEabF[24N`LZ w/DlZ`HJ`HBJRX&N\eR_ IkhFLTh&/$E5QtHvObEH$qEꤤ- RE; QP;]\7hb7چ-e.PDBDSxEXhIDD[}ā'Ipj/SЎiϛzol[0>mA?.=xS>CS:nu-;z{~z[`c=-֋xp9$O!M9(zzU$"ȥg ݶFN=Drik;v'?fS:[sai\@Tc@NM~b~۫RΦ05v/"vK8]O~ Pl!>4Ӧza'i<c88:6g5xh3ʟ;V%/g>bU6U]_8FҘ NʈG=;e!=A=0uou"'Y廎9L9֎%oضE&_p6 pr։w}GrD_TR7Y8_Tkaڙ#/8S 6mR "!m.CT// |"^*(4dF<4LX /Ðվ(?Oc|ypf||ь|qfS%z1`=DXFbqU4،P~`qGPyr-m_,OE3/]wP- 0T6er\)T_?L;==RT5=V> endobj 52 0 obj << /Length 4254 /Filter /FlateDecode >> stream xZ]߯8KX03ڂH(Dl) 1wǂ>{yヿ$?]1?_4YqW{z_=Xv;],w{$7=5ĸ"nnҔ\*Tm=J5|>dO,N>c|=sǔZ)Hȁ>}~7/ygӏä&.`|gkBҽz(NwGZ?uydu mZgɳjLNjD  1]-_1s*T7(tG|4ۍ9Ddñ3#Էxl>^Z!Qu`n!Q!6P̿H~EAaAxfCYl4YQ qS!M 5"2[3*Ė]罘Mt(j䋙wsN xm1g!/.usnwT\/1w/^K$m-39 ˆ)?G_Nō1"=V;9*7H[u5S|GX+ 8޸.v37?81UԠ4u<xbZ@xzF#cЁ;~ Hd#cQ2QPӄ0 Epѯ=TZB\Pb߃@Ձ;Ґ3dt²]8d(0Z_τǺ"ӏ1! w$0G_F,7Zvt:ltñ?lϗF ,SUO96U@mU;آñ+^/Qcp ')Nǚ.G bq&|hзA42Ԁl uô 1eճ%2bl> (0\-o||1Q8\umm (v2dM&L}vec=^- ዔ?%;; ?}M{( ^+C" )bn:oE4Q Jj8D"rr3xŵƂNBfQ0іL4Mԃ"S&V+n󥚨tBM0<~W6ԤE+F-(@{, x2OܛR76_ EkՍFTh&/$E5tHvObl I+G7ً.II8zw[awh륺)Totn ,eDBl)>NTc\)Z-Sfi+~:I|IBOtS4}y)'^$O8M$Z&-x~Ҫx v񥩥zLHB>&)9F5Mȇ?x|*f)L>!>>_s 0d%!#|p>Qq= h$I'ɽr" ڬu` J|kR'1ix>IKD tA4 D%L}ē9܏XuG/|~DOf%77#iSSrD9OԷrmS68^dO,xToׁ>e;DWM+A݇ˏ0&Ɵ<}4=_-C7_Bx_+moƫx$# u=G<~K: vo|ns 'x 07#ߺ5;u[+_bgA|DN= 1ߡ'8Ko#M+b6Sz0L=MKbSn ?V5KX֯KaTV= 1xH2q]O7D^ף ۮw"xwꩍ]occb;茶zN=~8~>o `|c~+?g;ƏC7_~O?ֽ [~_?O?mcc?-xp9$OCӛrQ$"HD66;t~905/S?᧩m|D̦vu$i\@/n91t<;ǫRΦ05Av/"vKxb~=] @ٷ'N'?=vlbEKvf$"]fp꿙xQNxFcHÞe{;!>$*ˡl_Q-,lQ^IL^?ΜyvG[_v9kfigf,V;3%fPOj?ZtL{UM3~}}lǺՏ٥^ Oe/pO3?bU6U_F8$*v3/; $/i\gV'$}qFNp}~J&k˒7ILdy mD4rw}cƣL;!Q~C/A㛉,CO\/L0qH ]I ԉ!$-;eؗeECEź^ g .V0_o&O2X^t.\yJ`7G^4Bhzb*T^ 5\zb$z'^uOp! ʚ-,h#Ե^]K;Ћ/u{I\tǛa9|Eu2ovAW/c!O-߈k|T$2gAaX|&f;<;4|7M1j#7|Ʉpҷǝh_L=P- 1Te鍊R^~虊ѥw*V{z襪ejr> endobj 54 0 obj << /Length 4275 /Filter /FlateDecode >> stream xZK_ >]¢3ck j+M. HSH=ǞH(;s3/^\r^ϯ^/]?y;p}5_}|= #oC x/TMzy=z2w{ͽa{c[^ws;>c^?z:[7?9!bOmtE#z=}u}wzOO!=orgO^~S۸.RV.M%߮5ۣ[HWn0K'ys{$1Vw߾mr>+߼xo__0ػ^|t?iݑ+ib΋:<:vH5zzjn<%|0Bc0S0s2T7StWn n 6O30Uzk&/p'[yc#- wz UC2CqhgC#)fqaG8;a [D_Gzla6(j fj|-*3 BtvddVV'M8l[nQA\:n‹Z #eb9"3nc9n¨=vGuE" cDm2%}fv0'"pJyĝxq#zut{cdNJIV=d`X3#ZY@;Bxڙg [4=d[2VQD( :}s#G aw p>@j1ё<G2@e2ҧ n`^˓1z- k npF@**σzUݹ!ਗ਼plg!'qaጀδ`6`0lTm5_oHJ26Z_τ:#cƃ(9bjCŤ?~`g=&y(" [:rDo׊GY O|7?^r#6`~ RO<]ҁbxݤxyv>f>|1_W>5XVL|%!;_WЕ(wuX5bE&ǃo[(훏@Tvp8 Hv*u)ZY7mE ߶bАKPÌem8P,-%a B"Ǘ\Ma!OddMGhם{~lxNj㡅{}Ya»H9Ltvx/akw'I"A>SD"쎧hՂ0iyVm @ O/E- `8<>&B!qaB>8,È7iB>4@!OS1|Ha Hȇ'. &,mOH-yH^-ku6';&Ifæ'&*ux f^j8ĊO`1 2lQO,aD'Np?b i/~25+7mI1?e?%M;ua/~ܸ l}##EXRK&|hlzOT{he={ 0нxZⱟf_]xx-6g)OhMckkD{*zAˮ'u\@^ѮG=ۮwEv=㮗wmCQiPfk:9m]g1mySO_6zmƧW?ǥgouGzxJ𗶞">nE|Suo–^Su {@z.D1D0)E"RO/DdlֻȩzY=M~mn#'lj^Gbz|N=>l6>z^v iIO_sq{Uw[ l Yn"B^ڭMfnK f2:J8m:wvOcA?isFP6oyfF(myksLAް}lEv<P\_ΠdYR.zhrK63br*3 꿙xu('ѲC6]6mol'ن,^}E\2ݮGy%0y9 G[_v弹mkf4MNmSf%7ԓGnSUӴ>f|۱n~1؟PދϠT}cUr!V5i_ac$ QAxC3^v}r [tI^޳ )\gV'|E|P똑?qh&?UC îLu=m$z7^uO~xey4uW)m<^]ta9AxuSxeǛv;+q' okxT$2g╎AaXxvw]9;4c |d:s&"^gj2"\q;{ CeoTJ|Rg*&GAX=?Ӄ/U /OUۃoM>ϊnOz<\{Q/l=zb]o|Gzd^zQx>;g=9njG=Uz~[`;35UtsƗЬWEK>@<]z0"ЭGK 3ꧩw?V/=4w%;Su- c$&[wl#ѤCjPo^`˗4"[o/Wio^\zOp/^6N=tvpbjԶ^?GAKo*~%OkWw5~Ȇ'x5UQnYg,po{[X7yK_a!'=jLcx/>3endstream endobj 55 0 obj << /Type /Page /Parent 3 0 R /Contents 56 0 R /Resources 4 0 R >> endobj 56 0 obj << /Length 753 /Filter /FlateDecode >> stream xVMOA ϯ·ww *P[&RJS@Ig<*B/l{9XuEm-l'p:SFcN)] +V vlD؀ QID|h sPp֣!|APDK/Uf}C%lTGJX (Xg{sc&+_S}17 Yѥh!hoHƉCK"81f1{NSbJORURCO7IcD -wܥ`) ShhѥhxTF<\FK L3K?ŗ-:5׀E#|GcߒyU/^[мm6]:lOo +hSݞw vgNIKƖmHxA@Ub/i #1y> endobj 58 0 obj << /Length 3636 /Filter /FlateDecode >> stream xKWi]5%PRqbkZ{U}"|[ks咖o_-?.XֺTמӺ^tų۶n۶_7˶떖/ ikkICVԖ˳Gi=&޵ux =𮽎ճ}l/u_6G^q;1`ߍ1/=1^}{oӒ2R<X>?ayn(^{?eۯx{>0Go/Gx{9*kɔo?ηru|T{큭3>޵ݿHR,w/ݷOdq?]|W/~xOYa+=sgo~~Wo^w[L~Lֺ g3]<3ܗ)cm;:68¶ͰǾ ttaXf~zxka.n qDm[58Npf-;Ճ9)p-9i;$LCie?TSp"cHޞ׌qy=u_ۺy}m6SX;D}wo}0) z\y0~,OLf\ym~۱F_f󅉭 9ͯocfI0j6g)ͪ6ץ[&aTBJ7I|zBYDb]Oɲer1:b nQGeQ ٻĉxm3a0#\O'7iF<z!\OYxțE<ȈГex#xp=qI#{(F䣅 ɟh0b.`J#I l'T'~$^x='G"OjEMjSo5DKO/X!,1ͮ'kA DR0M#i}'V{\he>硿Wy}bG5Śo#xX)z<$ңXzKΧŊEx+ނg<bųX.OOH]t]tX~).z:V.z:Z.z:^| /z:X&x#qgrәg+f>+_|.W=z@\zD7ĪGUOq>!q鬧墧 _t{bՃbՋ_G ]tb_s?< vS7ۺQFVn egNݷ[|$ ߼*<]`>L+; \!L[r(}ngZQ3EN.?C*~\_Rv^7 >3< þ'7\u±;W5ߛUޝH9Y9((^3|XyX8n3yg\خy0;38lw>K5پ~vTŹZ -ٙQiV.ܜo&nuw$eÞe};La9mvWv;\e:,-Œ'LqT.a̮g;Θf;dgfdnvfJ|0W fKsF}܎M/V.-WX?f?c9W-g/eY)9t yb=]뇗\O^]Rwtf\e~E}|qFNp|U6XV !~msnn9 }h&vp>g.c`XgGrH[,=3zE"vI Ilcക.ж܉-JW-x3k2R'FQ'I[m([U` *$bpƇ}X'a~aV _Kd?Nyz'gXks>Ě/oCk=z<$ңXz zKbCIx+gb{B,? ~#WbY;P, ~*ߊbbX x XF|^z@zAz"xz^ X8_⬗ĪĪĪǂg&V='8AEIYU/zW.~qYO;vl&_U۱{Tm=vkte_n#磶ݪ4{U`!?.o$)`"~z7Nlendstream endobj 59 0 obj << /Type /Page /Parent 3 0 R /Contents 60 0 R /Resources 4 0 R >> endobj 60 0 obj << /Length 3459 /Filter /FlateDecode >> stream xZK_1KXd2ӏ-(HĖ@,qm96ג ,{ϭofqT/p|qJG3#txH 7Ϗ?_>;>pu'-񿇯>_pSj>0%\Ǔ_Y:Ϋ}@ /jS;s2ʙ4'tV>熗ӿ>߷^?{#D% +nx$˛??_X:/~yOKzT՞隅 2kޱO=Wg fwKv; "[B>釷 t5kuu|28 SO<iy,l`[oBC}A,A\O \-{0O`_ "QY>H$| a\7MH._E"|=X=DTAU# zͅDn ⴤj 5Q،O oąo|~J!q/z1֮/lJߟ-Ff|55*v|GIr'ܿjOtw7X6b~[jqßp{@<4GJw`z]!P(KOqz g}QrOtk`sL= xzz878Q;ezT N"w'>H4i$U6`&nXJud!BE2>!)#2"ˇo3ohylጳSK#gs. E+ǡ>1b{sƄg_u/9M0as ϢT\i, &8&Mx:G(NtORT\i/\02ïz+#&{.^p6`af7_/<"M:6e45h(P - RHc!;|3FqŲ0HEO*Si|ro&m39OMє|>EhEO"SD=D=_/a'Cܮ{>Al+zj_-60 nN~`-Z!-I8\;?ɵ)qIO&\Ow~hR|:D¨O"O"e AۖOv~CWL L/]5bS{m Z$jx"98R$GսŃD]\8}O$*x%|hVf5߀[vD>_[CYBz`^1'^X\>X=>miBW= MV\(OQo!x1_Q->4.;:V\c(_|I+20|[ }hU>&_3K艭|O !1>D8o7Ĵ~D_ -Cb q/eLOY%lƴC{jC4~KO_HoG+ƛNϏ`z饞|z͡OXC5z#EܘCIC7Q"(ի(Dgo].vz4:]+OjUSrz|CuiIvjG `iӷ@oڕj[1^,|'iu>0!qc(L^=/]_Í Qt}cB?B&ʵh ҐONA "xdL,l&.p!x^h>oS]gj_Fi=2PhZ)v"zNꝁ7$7R`b@H(MGGb|$O>K]>.*}eJ=_OSOM'h|O|~@]h_W?o֯\?9~!r/iBF 3gVfr~rZ>!@OזMot"HG8P| RjC~U/ޯhzG1E"Dz㌥w#Dӕ87brՓ4/T&oUxJ8_:=]8hzwڦKfzxGz0ڸ Ey߸X%?*[|X7(;ߠLK=8/?yo^}E# endstream endobj 61 0 obj << /Type /Page /Parent 3 0 R /Contents 62 0 R /Resources 4 0 R >> endobj 62 0 obj << /Length 4215 /Filter /FlateDecode >> stream xZ^Oqtm J"$, 1MyTu͎-aHs.3=sx}qǗOWwЫʭziԻKjs^?~E߿۟>>w:ſ|W < 1[rP7<Ƴޡq{<{]{1i;Naxt9~#߽yO||?&?]1gaƽ^O_^?S{;bAEޞw? `6nKSro$R(0%5Xʝ|ǝTTVM.) 193BuM'|4棑䆸 LDdñ3#Էxl>^Z!Qu`ja#` !#vwG+" R qƁ#1Nk;y.HvzjA>^XfBXy1=ɢfܽ.DZGXXa~N6l,QjͣF)BFZU6όb(]#됍& "^68!n*`iFDrpFr[m|1AŜsEnc9syqs:z{X"mxoI|QF|E$Nɷ4_/9Bxp/nda/X,zPI)`EU2{;Z\YȀƍvpɵ3ϜA1h~طdP!`t+*w3T O]$x @HDGFr=$[ˌ` E(qPʘ&a(~-OX"TTޟ" 9!ਗ਼lW!pDCJe20e" 3qFeHVƉ$C׺Z~&<~)6i>5'$9}P1>f9|լ^^9d#^*G|#$ x] b>|H1_@X#^TKO``r<ҾB,ZL?ڋD򡥱oJ-' : ;:b:@C(]a2W``BC\ d ]~7b=G0#1cN'_We7\e'hBv y \J"b&=kU7,&`VTIj8 "D$r2x<=R5ѱ]KxqḺH$Ud"g"j 0C4͗ٯ&4l;-)$VX$b"i܇YDe"^CF<6d&E.|(&E{M`XTM&X?z^$&JEФhꜤ70q>l)&-x~Ҫx zv `zLCB>&)4FKȇ?x|*f)L>!*>_s 0d !#|p>Qp= ?RK.ɫ[bm#jɫaZNHj:ĚuI'tyw>] S(N OSxQĪ}ݜOЏHܧFZ`$-}vJnr;u>UN\m}##׋ >6a2 ϗuzSuѩOtgXd}H 1m1}}585x̧BhzZh#~3^moƓ6n~P_ⱟs7\g/ܯ'=_|#ϒNv3nX6=v>P#_Oʹ||勩?33eS:M ܡ'.Ko#M+b6Sz0L=MKbSn ?V5KX֯KaTV= 1x1q]O7D^ף uۮw"른_vH11zS_g='VL?@ \?7eTo0m?m3ouG~|J!/m?E~F~Χ4-Ư붱caE<~'GozS?D^~Ȧofdr"Fveg94~Sل.V=<~z}`6y~T48&fSCvxUG g Y#j¬?OxlHx|/R!~3Nl}Zz퐕qs쟀/Ϧ&f^Ǘ2PqM3y'!䳀}&.6o0ϟX) Ccv^ \/ߘXvȘ71zID!fpMocCa!iOqb᥍v}ӱwbؾtP?]xqPqwv(#)+QCx!(q !NSF[L[B6;l_^o}4[<ף~ ώ,j)oslLK;4q?Yv(Ix/~v2&f8?u; 7= !/K\>'1?~6Uϥ_F84$*0/P NWf&qMp}~ %k˒7?Ldy lkD4wscƣ !Q~^C/.㣄}w׋j6LC8􂇖~&)+ub et~z{zQN'21B!31Cw1 V[ 4 W}SE3!Tơg BO\/EK'FbqU4!^F;\UA XR+Ew s?׹_]~*&n2a񍸶GE"3&_gbAW|aO|d_{V>rיLW>+v΍y{ CeKoTun߸.?_nǫ}W~ǯn߷-@5K죟(_h~t@ :`{E\ϻ0WVo xHG>yo^\~5O㿄Bچendstream endobj 63 0 obj << /Type /Page /Parent 3 0 R /Contents 64 0 R /Resources 4 0 R >> endobj 64 0 obj << /Length 3601 /Filter /FlateDecode >> stream xMﯘ%,2ނH(Dl) Ă8alD~Ωscɐ>oG:U-on?<}sOmuomklu(ۛ߷׼oOO===٧_DZ/)oo2/oȩ5oⅭᦾ}={=‡i^W{IXm]s\W{m^j|hexǀ0Ox `Şgsl_mx{?ay_Q_jox{91g^knz6joooPjޞ빷 zjR5?k}/^=j=p=jCFK[A`߾_1p觏rl|ܞapWo~߼Уӽzjɏ \A{C]ÜsEu~|EcfJ@,/r ~DZ zNNxky짷fRabsg /kΓqI[ȩ>59)pTM9 |CN>6iݸgjd ^?._=7n3>x?&/Ӥ~xIޙf8cyf2qgo5 2p{s/l6L65Os2ܬYas]e',0+VS醝D7̗b0oRGdBȜF-37-[!{ћXyܛ/+e"C8u?q:U7ds͑E ߋ枩nd{{ '[!#pNj?gY}r/>:N{ǰcb`çB %q|E<; ~r]!3Wngzƹ?@t9Hy@ \A~rE=" 1XL C-FHb(F8Bì# i4#t^;3V0 pba~3Dt f=tk5T>Zkc;|]+xoKkZK ^-ҋXzKobQ,:_zKbŃX"V<o+ŊWYx $xX~$_gⰻᆋ,aÉQ/_68XIbqőbGZ jqő~#9.ܹ8Rȼ#1/-VZ_YqfX\o~*ŪHW"7**"*&qUqLMo~qU|zb ^xXŪh"_:Pvq3UU2?0݌bm?xNm w1AH3, vKFgT]Cg^ weYD+ JK*dAZKz}g+e$F ƐrMtl ^$ Lg13-vn mJu2"Cֶ0i[?`^+VR}g$a&]hIT/X2[,xFx?eu|A ܫz"w= m !`\Xb+ٯ r =p'ԭF<$=a~' !d٠ H \Ot-\Yg"`O9{ɳaؑ/m#u=UBO7OX]OXh4$e8yPyz O'~$x=n'G&/EMfS粧zeW,۔?bb*DfUa4ïy;]Ml:a軬z^zXbGkĚO[^%zbA,/=7(^ҳwAx+ĊbūX,V/F,?.?.?/馧o˯㦧+oW>|&7=]0xKicuqӪUOzCzD|zJ\ozUMOW'V=(VIݟzT\nzUMOW,V=-N7=]OW=/.7=]_b/(n[P}$LY0K<}rzn~3x;$ 5ֻ }<4U5}ՙ#37i*@覯*cV}rg1\!tNʛܭ3*OÚpnx8WϚsM]1zjW21A!|2Osae=tl]Bd{87Oiю2:7wv(SwK7 G6QSi؃cXvbߎ8䨬0?a_پ4|r<|X)L^: atiCCnq(E jdηd?0&W77߯%Z}3S~c=VOW?9[959_HSKV*c=Co'Ƕf8i5UCN?*>Xo8~8>nl~M ?E?_g7S }B(8/ 8O&FvHX<֙#W _ K\uė;_ 1l5rno`  1eIowb ? 4?bGKQߙowm5kɁ7nORO/N3?i9 l +~zX ^bGkĚOkZK ^-KғXzKb5xY,+^Ċ'Mx ^*V< $xX~$_gC2xX~+Ηb/'bQWb3]ʇbKX6xcX> endobj 66 0 obj << /Length 3423 /Filter /FlateDecode >> stream xZK_1Kx[$J"9 eaya`r~GU5 {n}3]Szp<9KNC%?7×WO>ͷu!OLJ}OW>S8^|:Ϊo9f/}Bgvf1)=}K:{gfswoSDĞa{aŭ^_y?:gtuE^~_yy?=Gw<=V?)~yOOUKT՞R=嚅$5'Ohz%x-,w/~woQ GG/^}O~zٓOY*/߼| LA ? eE᧟ƜZsHuƻNJ o,pvrPA[>3%Yp]gL3ot*`^pCT錛 ud6{$0y\β=]gE\ޟһaTf/ngd7vg_hS@L)~_g㙼?t͎n󙽿zO9VYlt6|X7{=fogv@9eoyb, p ]-]]V QH7{۸"J|{>I'/"E͎_l|C"O<_DIi>|'af O_pAijJucaz 1e?kt:q?A (7p.wㅱ xo D˗O|$5_$2gO .sߏpˮ^@D5zZҭALk.$rg%wU *Db3>Q*i|V`|X7BӚop42clyWȷ{8*/X\?gߏhO_YnfF_֞Ox~"_)~ qO8=}%@<tjN+4 ûCr1P)z+wG=Mq N11nPOHLӃH"IDߪGQU$RzCBrz;^FLO#P*C61vòT# w/jwHqzȼ}CC g]&^>"=66vóp0a5 *R\G/=8]x9G` œ >;Pؚ_bau~a_/\~(n#kF.}CV"1_ꂊۨUc8.]R`Q=N$_o QFv/ Ds哪(m)l>b| VWܶ|!ϧ.Q">"ĝ'6=ï).=E=|$S^CO)bů!n= F|BLz6W_4-F37 2_POM|jy6u˧t8b)];?k秄.VS ;?%tͺ]_|JqP9e˧w~J0SJi˧v~Jmd秄zya,>O8<kn= E"~(/AUۜj'Umt][O'=1&F*/A'~CLGL4^1YBV#N!1.iyެSُc~ccω!s!^y'/$ 7T#gBR |]zG0=|RϿhz P攦zI_fz=z`MqdN"n)Z$ /MvzȩG* SY[uz F23;=M~NoNx0P(l<%Q)Ood7/` f|tT-cѮT|D'1.|㙷rOWa΀4NO 7c8nS\8lF>t*NFq|p;q378S/yLGGlxµ=U¨?²p8Smc⻅+i0S.m2Ne||+8o|J װE/=31eoKSo,7HPv8uVzm4y d'/|"_w/Aqa!Qz?.=O~F(޾`)uB}  =$b3@tbƋSXxM\]>px܈擄^o NGA!jJǠ1h>` (|4:[$ C7u#F*ֳPhwi[| H!|"I$g~T;C~yT|*|+\ZĜ e[4']? ή_t{~үoxo7W}}qV WuTgnjկ,_/ =ߢNbzDA{38Jf^b_TbzDyw1 FKϑ8/GN >M(WzQ1)A<"^%oagoMӥoKklz*{z k6/vDG tGNGZjooW 彯C A9o~_?endstream endobj 67 0 obj << /Type /Page /Parent 3 0 R /Contents 68 0 R /Resources 4 0 R >> endobj 68 0 obj << /Length 4130 /Filter /FlateDecode >> stream xZIW?;ڇ}'OWwF> 3zB䧇? )|Ͽ;q]G v{ o=n{Jnn)5 ~{L0%5X->.1>{1c%QB+ło?A ~yIx_~דGT سztMT`džNwGX}΋rG<ƄU%Z1A˜ /P}( .wKJFzk3#PpKX;p ,$] vw>62y1rAq|x/&<ݦ'95|/v+030w/ON7`NJB9GH+޳eWK/ Ě=қl>c0& e37cpC%⭗giSoMCO^4m'(G w>"GgwZ;Eϕ/Χ+bM| ט(ϳW?D~|[~ /_?Y~&^nÍ9P2}%S鷲ckXo=`xEƣ~*d<Ïި_f>_~x^~_~Xͱ240ֻZ:_fYVbضWe)qP%XZ^g +|ac'L>Y lGQ"}nNVkg>uv<Ə?RI QKfoF1\G0EeQrZ֓lrfO b*QŰ],fsP;6LUB(e1]XiUchC5{FU>`*U*mG/\+e%F5,wnlcY) 6_0ˉr*afAI^Q'L`ֵ,$.OҖ%%YYY\1xEW^]\t51!r!뻳 q>QGwqyne׫220] ͡ LW0]9>_|~Sc?>608z=E:%͜O]'{?J<Z&cB<88q|Je`/Om)ă'A<8< F$A<#\'iaχ Je\+OTV̷'`b3~01:O'Lwm >` S*X<#k%d;OjUl SqB:0d>E|KgBl2&6JIⵇ!ɛ!C8>R.%ă X\WOtq} zԧlcu?q] >agqySM|g9 {*~;w7]hV5jm5#I*_u6H\&xK3x!f㵙+C{?)zKo8SY/Ǒ~O."qS/㭷ܸt10׿?fm=w||D| p=:ϟ1ȇ3%1ySò]cbĩ|n;} N'MG,C ]C~9_"N?Eoϩ~]~s?9^| [~.GHz_mVl?[*[~zc:SoWǁסqz.ϮU/xb7Xkq2#)ɜ3k~C5gz{l]~ szQg\Tb5[W&k/.ޤb6Gb':tlY=.Gbò7[+9@~3&RFW'K]_V:Fitk!w]48VJ 31}[х L !'7=]^_KɻD)K[Jqt5_Hs2dtMS6}Nqσo]ďy'_q?h+"?X?B?PڲuN3'-l}Q8_['?e!W㫄}׋jKm@C/p#xS&OYCH([O<~=]abE'C/TIa;ӏr)xzU`} =za]mJ쟊 h& =8 TiC/4E^6'F`qUD{>\k {=I֫~z7ƺo:<buq}~M>p'_BԿb/>|T~un$gbvw|$/hoƓo*g#|R4q;izдD/Ko4O=Rܨi땲t&i?C/U/KOU[U-=z?zM|<\id뽎3#_7|>O3W6#qz;̇\?G3_rڑOӲ-ay^f>}{W?@>xOd ~DQ 3w?/?4w%;Su- c֓ӯQwIߣ5*hE O^~҄na|u~TYWmn?]~~OWv5xk6*i{ɮ' Y!nQ>VYe,^Y#y~;:q6}mSC!xG_>~^\z_5nT ߐendstream endobj 69 0 obj << /Type /Page /Parent 3 0 R /Contents 70 0 R /Resources 4 0 R >> endobj 70 0 obj << /Length 3543 /Filter /FlateDecode >> stream xK%+j UYY[m ٖbc }ND[ #^tljyo>ӧqmg[ZnYz(ۛ߷oyOmxJ{Ji{_cgoiS>2/oȩ5opS߾^Ӟ1h{Vj/ ?g{C{VCuv^۱4گ_c;˘Wof~߾,X?mK|z|탶n/~K{/;c@XE~~q{^x}t oQK~{Rc=ױ =TO{ߋo_HrItv,?7@A ?~c_|_z`ǯ|շ_zt秆_01~!,gPe9:?s^Qj﵍Lɰm 1J{N_\ t+0lKma%p봗.p޻[b:wT>Ǐ|yڃ 3A \gϹ;k{c撹:+R|fǏтJqu'8ðD91'_siR0titf8`fK|y=3VX2uese1_5y_TaNh28c=Ogwߡ80r=UV-}.\H<0b#Y`$eWba%n`3݂pS?/ |t+|(V+obkybb bzUUzF|bCbKbS|UzMzNo~AqŪ'Ū7g=*>o~Y]qŪ/V8qfw,7Xt3p<&q;y61Xzw"}\G;+Z-M~TAfa4\Yrb9ز2#ò|>dzbxv&z՘_SFD*ZVb8_;"\O\orGZ9P%-=ă]A< ;/zc C\TI G=![|?̴)~бu=j'[f{GZIk*eHY^l[Y:bg \BO5OJLYsG]T-ӟ SyR0aHO^.2ʠ?Boz#~*7WMJ?Ax|z^ =&:hb3|˺^+xoKkZ^bX-KԓXzKbU,=;/bŋX$Vx+^Ŋg],?~!7b8LozZ~(_MOo|{iMG󦧕g+f>+_|.>z4YoUf=#V!yӪUzM|=AYOQqiճV,V=-N7=z\|UϋMOk?< ~S7=Q' e>y>'ьt3߷?wd~β'Sr?TjOMoȶɾߩJԭ t~z%󔝟CLFO=YΥ:SaiܭF7>~eT"l札T|Wt~m y0qU-iS|PUT>ӎ/IS #mY}[1~~xϼSa2'l,zGK~mOF $?4F `b6Igf+#bCٳW|9׋<<#VX !|5kZK -KԓXzKb5xY,3^Ċ'Mx *V< $xX~$_gC2xX~+{AbX(x+X.xCXT|V_endstream endobj 71 0 obj << /Type /Page /Parent 3 0 R /Contents 72 0 R /Resources 4 0 R >> endobj 72 0 obj << /Length 3352 /Filter /FlateDecode >> stream xˮE+zh4YFH8ၣ( I%⣪(K {n>vmO+pU)0_9tQ!ko//>/x@zȌzkn={{(l]{Ovҭ ]{O7khkݍk~}}?&?]1?_8ʽ^8ϯ?Ƿ߽oABf7_>R>{g?^OQM2//|g!t_0kB72sHKM|rjVGѲյޭQRldtpaCs oa 8,;p'b&'`iW0G`t 2 !4=̣^WJ-0svzDދiV/(TVOz3?hHz%WW(V1ze iK9zbhz1?H/zu'/`7#xί!g0 ;21M7$񙝟oa"1pc`5Ll\?{`OxyEGv~R59)ܝFu~BJ>Kqa~ -~B'Ԍ6jE y6_4&@BBt;?>:MqNJr1 skh^Ռ|`'62B"6|SfSf"Kq{6i.2OP^*ܦnc8Ip;f .K\Pv3b);|wT3KUM3*gT^U\O،,D\r!}Ff'q=_OꢔTxJPYOO ]x>SB7_'9z1;.j)YU7#|<%䃏|~)!|<%C#|<%Oȇt\xjOpA䯇K"?Vxj')Bzx|S/ӵ)#>42DOtDb=#(DD'Jie>ҩOt>'B>~ԏx">_#pd$}v oXOBgtۘH6\lwQszЙ^iNOyt,;=B!›^ˑ ^! gz o=c{lz+GN2~20BA6 W -7,ꕰ3aY]F`dVgKFVO'거׮TeWxh~,fWm 0_NIԯ`4?#]ߑx2$+9x_vĶg${%r<М_Dc~|0)z(Iv=WΘsW~SÒxeOE_HmΏuzg\Sw~_:~,fss)W zUyJ\^+㍸1fě2S/2w}֣ ^Sej$,2S>fzֻMɷg4p\7; K1fԓR=S:O6uLMyCuƩ/HSmJ)xj*#RZ+Y7SZxs^usgEyB+!<:_ra6…m:]apg[Os[x~qǹ& xd$25Wga̟;qw|`$> L> endobj 74 0 obj << /Length 753 /Filter /FlateDecode >> stream xVMOA ϯ·ww *P[&RJS@Ig<*B/l{9XuEm-l'p:SFcN)] +V vlD؀ QID|h sPp֣!|APDK/Uf}C%lTGJX (Xg{sc&+_S}17 Yѥh!hoHƉCK"81f1{NSbJORURCO7IcD -wܥ`) ShhѥhxTF<\FK L3K?ŗ-:5׀E#|GcߒyU/^[мm6]:lOo +hSݞw vgNIKƖmHxA@Ub/i #1y> endobj 76 0 obj << /Length 4240 /Filter /FlateDecode >> stream xZK^ .aۙP[&R) JBI=Ǟ!H8s3Ox}}}zUU/ztIwNכ?׼ǷGO!\O>;>G>_?"/7Pn׫BUTדǻ-Xz)Z汮.<{5u7hSX<{{nq~ÿ޾ǿo~ {o+&F> ;z@ǟBy{/˝eߞ? v{oO >n_vrb_viJ,*Pm=J5|<6wևYʝ|=0[>NS [h%Ypo/w? !Z?R>xg߼͇_O?yx_ֆN{Pic#\piY[H5zzj]L[:6PLa _MKwHp\D Lچċ!ɖcgGoH 1}޵Ea3`6Pyڙבjp?T#mӝ?k;y.[s$^\A=zt_/,3tzv[ymGxy3.#O]_pF؉n~N\6X՚G/RfTόѕNؑuV9Z/[7fmFDt wFrn /j%b=ċcU:sɋ n&M/%ݶɈٹ )?G_wNō1"=Vw;1*ɃBV$Ycd(kqf!kg9pcl!o#[E J5NQs6ՀI1zWMjPHEA?`t W' ߰N O|7?^r#6`~ RO<]ҁbxݤxyv>f>|1_W>5XVL|%!;_WЕ(wuX5bE&ǃo[(훏@Tvp8VR;k-,ś"o[1h%aƲ6 Zb(fTϖKg0xjpzPUGצb'k2qg&G?+xh\V. _D&:; ۻ7YL-{[•I"}l."EA&ATfGT١4lت Q<h(Hxq:$iI mHH;=H2jjE$md5_"jep!)MZ"a O)IcI; p~bl.JI\$R~&$nnEo2Ql`|D"=N8i#(V. ](Hq$DBKvqQ袉h-j@' mMq)fu⢂6c9%efwmeI`S$͎')<T/O8E$xV-?x?aՆ Q RԒʰ㉎yc"$!&)9x&CLD|pM<ȇ&_j߯|x꒐iA>8Ȃ@/%/ɫebF$vǓWڀr# ܬu$DOb"!+|T ǓX0 "tA͡4 @%L~\GQ:ףtmZ/:ju~XK<,{ Zkj2^mo MR$bxvog /'=_xˁGΦNv.6=v>P#_``;xc=[[/&|wnM L>,6h|&(\wt,go'_&L>e`ɷi]|L|~M>h^|OBeCY/hwDXzCh+g1qȮsR;Xm11mʌz_g==L=@;x~>o ˆ^Coпm=  MNc[OSgԭ|MkynzH< [/ԓH<97УHDWl"m6tz905C/?ˡɯm|DMHlCσϩއͦqGϫ_@Sݎ9m6:ynw nSVB;Dn--t=Ҧ9z4®>C Ҵ'Nc|ӧmplڜ[Q1 q==tڜisF6C7l}]l=8|:Oz;T73(wv;YA;.^mn&ctjkp;}3a]jFw:NUtûMی#mbHNo`VV͌\ nGo&a]8 gl?ƐD {FM(j_XlUMWuyIc+HT;f(#]߇V]lt_/پՉ4d:fϧS2)X; QNb%|cO|(/m4)_[')ne|QJLg||Q]dچig$L5JڴqpJ6rW R 6TLxQXBА}&N0b5h CUf(op>eES}sTE3"TgO/OP+a]OǍW`3@Y}6B]UʵA|.?iCnx&^ghwT&^F|dיW>+u{@s|1@P|7*GqlR)~3T/>KUS[|"ۓiO>Wv>r [Oe>QWqz;Yy~[gQOޮnG=fbnp*O[Y8-e.6MnW?2~#FRG(E~_};O*Pendstream endobj 77 0 obj << /Type /Page /Parent 3 0 R /Contents 78 0 R /Resources 4 0 R >> endobj 78 0 obj << /Length 777 /Filter /FlateDecode >> stream xVMo0 WCrږ-6K,R$(Y vi/I>$ g`9<@kyhQw|gu`pd6@}|SNK0S8Sĭ,;W: a6-x Lpdww.cY V=@4=y_endstream endobj 79 0 obj << /Type /Page /Parent 3 0 R /Contents 80 0 R /Resources 4 0 R >> endobj 80 0 obj << /Length 4271 /Filter /FlateDecode >> stream xZK^G .X^fƞ׶*@*ĢbACTIK}αՐHMˢiW{|q}w~ܪFk;͋/7go>B?Oך<?9yLJ!rK^rz2w{ͽa{c[^ws;>c^?{6{7_.!bat??ٿh䳰^g'zOg_?~8>.wqǿ=3ޞ|vrbןviJ,vDFbtD;,Nc}{G\-')-,/w? !Z\)_O^y}_gIM</7/ L ?:MU;r%yӟƜGV+ӲjLNjH & %c1廀z|ulN 櫑*ݵ C-<`b뱑b;zk f!m83C#)fqaG8;a [D_w]Sߕ#HvzjN^XfB2 Ώ$f01z]x}#F؟Xld FQ5^6S[kV 0+#됭&s_ ?o*`Bt# *`y/v^oJ)3{Ή ,wt̙tFL9;2QRy>2P,>Mp`sZ#l`XKp3RQyTL{ :v4 plgOՄc;# q= I$8N8F(q gv# ma2$lzFR:Z~&<6(Sl |~7k6?hm׫o?\cد硐>ϋ<lnOAa_+xA3oPHiA.JGl46MYA'`'QV켓r<%mU$X+8g] d m~(o~,Y;ytVx]مgݦ?ce&Ϫom[X g>$-}+:r(R44R<5Xe]C1!̏9j+R]ME%8]zROE|<#E Kq"Hv*u)ZY7mE ߶bАKPÌem8P,-%a B"֫W\Ma!OddMghם=lxNj㡅{sYa»/|r^7ldJ20;5l WR&uЊm"ņRMORIdbSӰ"b2Fl ŅꤓPY&)&l%#M# Tki pMH~&zP_ 6iъ&':A>|:l\dK0j1 <6TL#Rx}|6aɪKB>Gx" zhh$PO^]kʍ$pa_`rǓXD"OuؿL~b)zDSi' [\=^~dcjpj<b-Ohuzx-67I7S;$zċG<ٍ?wAcOͦp&ѱɇ)|I3'Ju1mk55\{=mU Ifea: mzDYhף m;"qK`S[ҶǨǴm(35O~?3혶^'/z Aƶ+37:#n=D^z6T=~Mu;٤৯݁*ʇڭv6Mn"B^/oK f2:J8m:wvOcA?isFP6oyfF(myksLAް}lEv<P\_ΠdYR.zhrK63br*3 꿙xu('ѲC6]6mol'ن,^}E\2ݮGy%0y9 G[_v弹mkf4MNmSf%7ԓGnSUӴ>f|۱n~1؟PދϠT}cUr!V5i_ac$ QAxC3^v}r [tI^޳ )\gV'|E|P똑?qh&?UC îLu=m$z7^uO~xey4uW)m<^]ta9AxuSxeǛv;+q' okxT$2g╎AaXxvw]9;4c |d:s&"^gj2"\q;{ Ce_ߨ')ǕJTL.S?Ӄ/U /OUۃoM>ϊnOz<\{Q/l=zb]o|Gzd^zQx>;g=9njG=Uz~[`;35UtsƗЬWEK>@<]z0"ЭGK 3ꧩw?V/=4w%;Su- c$&[wl#ѤCjPo^`˗4"[o/Wio^\zOp/^6N=tvpbjԶ^񣠥7G?PM~'?odÉ(j p[\[X7yO_a?Kk\|)\_=/_}o.?֘H?~/W^|endstream endobj 81 0 obj << /Type /Page /Parent 3 0 R /Contents 82 0 R /Resources 4 0 R >> endobj 82 0 obj << /Length 762 /Filter /FlateDecode >> stream xVMO@ﯘ#^_Aj+Dq@K13%~y pAF;q'l)͔i_uu ~)r+MN;AmzX n ^'b8,)%SukjV.0{a> endobj 84 0 obj << /Length 4250 /Filter /FlateDecode >> stream xZK^ .aڂJD Ҕ%<D~ϱ BW{|r}w~ܪFk;_׼'p'Zǧ]#^㿯\b(x*n*ݖygCnuX~nޚ{]4)a=ݽu78\?go7Ͼ~|𗄈=E#z=}uw~zO!=org'n/mo)w+v{ oĒoWIooQڭa$+IId}zs{$1Vw߼mrO+߼xo^_0ػ/_|táTջ#-WȜ?uyd ?-TTV`"0]26S !1wWt9) :ૉn n]0x1;r-i!׻Vؠ:ll*C;/1:R_nbGjv#zz5_|Mpg><]y?bkċk7g_V}e.T_n+/O2oW}=݅;:bI ;/߉F0`Z^`3ljQ! ;j2G+eB -ԈH7nΨ [vb7MV[_́2Sxqr @ǜyN7yqas"sⅱD6ޒ>3;W8%k =:ñ@CDn'F@@%yP$2{Cb-,D@zc!ʹ ƈzF#cH;|8 pH`#cQ 2^P7 F0wQ=–78# HD\owKΐ vFTM83ד8ʰqDJc2l>pF@jgm0RKf6*C¶7n$%O|ӯgc`S1A wӿf 3J`}P1>fYI} s0Az6/x6 )m<;υ\鈍'حxdt൘7A7)x/v+_@@וOE=V;AIt38$|]|bX|Q".>J#ϳV2jZt[0lh/:Ȓ&vI8+db$؊w8QDw kg<,1Ql]v-q/>卶Տő61k'ϓ"0_gY-mWܚ̇`o@S Q=_XKr(&U1GmU+آC+^/Pb({)N;)NŚ.E `1>Kf#4Vu jl vö %ճ%|d>L@|5@(Z5\zb6psՑ)b dɚLܙ Ogʆz=Zח&)?%;;,?}M{/S ^Vp%%mk_7[ Hf+lPl(Ud$Dv(F:5 ."*i, ^\N: EEabF[24N`LZ w/DlZ`HJ`HBJRX&N\eR_ IkhFLTh&/$E5QtHvObEH$qEꤤ- RE; QP;]\7hb7چ-e.PDBDSxEXhIDD[}ā'Ipj/SЎiϛzol[0>mA?.=xS>CS:nu-;z{~z[`c=-֋xp9$O!M9(zzU$"ȥg ݶFN=Drik;v'?fS:[sai\@Tc@NM~b~۫RΦ05v/"vK8]O~ Pl!>4Ӧza'i<c88:6g5xh3ʟ;V%/g>bU6U]_8FҘ NʈG=;e!=A=0uou"'Y廎9L9֎%oضE&_p6 pr։w}GrD_TR7Y8_Tkaڙ#/8S 6mR "!m.CT// |"^*(4dF<4LX /Ðվ(?Oc|ypf||ь|qfS%z1`=DXFbqU4،P~`qGPyr-m_,OE3/]wP- 0T6er\)T_?L;==RT5=V> endobj 86 0 obj << /Length 4254 /Filter /FlateDecode >> stream xZ]߯8KX03ڂH(Dl) 1wǂ>{yヿ$?]1?_4YqW{z_=Xv;],w{$7=5ĸ"nnҔ\*Tm=J5|>dO,N>c|=sǔZ)Hȁ>}~7/ygӏä&.`|gkBҽz(NwGZ?uydu mZgɳjLNjD  1]-_1s*T7(tG|4ۍ9Ddñ3#Էxl>^Z!Qu`n!Q!6P̿H~EAaAxfCYl4YQ qS!M 5"2[3*Ė]罘Mt(j䋙wsN xm1g!/.usnwT\/1w/^K$m-39 ˆ)?G_Nō1"=V;9*7H[u5S|GX+ 8޸.v37?81UԠ4u<xbZ@xzF#cЁ;~ Hd#cQ2QPӄ0 Epѯ=TZB\Pb߃@Ձ;Ґ3dt²]8d(0Z_τǺ"ӏ1! w$0G_F,7Zvt:ltñ?lϗF ,SUO96U@mU;آñ+^/Qcp ')Nǚ.G bq&|hзA42Ԁl uô 1eճ%2bl> (0\-o||1Q8\umm (v2dM&L}vec=^- ዔ?%;; ?}M{( ^+C" )bn:oE4Q Jj8D"rr3xŵƂNBfQ0іL4Mԃ"S&V+n󥚨tBM0<~W6ԤE+F-(@{, x2OܛR76_ EkՍFTh&/$E5tHvObl I+G7ً.II8zw[awh륺)Totn ,eDBl)>NTc\)Z-Sfi+~:I|IBOtS4}y)'^$O8M$Z&-x~Ҫx v񥩥zLHB>&)9F5Mȇ?x|*f)L>!>>_s 0d%!#|p>Qq= h$I'ɽr" ڬu` J|kR'1ix>IKD tA4 D%L}ē9܏XuG/|~DOf%77#iSSrD9OԷrmS68^dO,xToׁ>e;DWM+A݇ˏ0&Ɵ<}4=_-C7_Bx_+moƫx$# u=G<~K: vo|ns 'x 07#ߺ5;u[+_bgA|DN= 1ߡ'8Ko#M+b6Sz0L=MKbSn ?V5KX֯KaTV= 1xH2q]O7D^ף ۮw"xwꩍ]occb;茶zN=~8~>o `|c~+?g;ƏC7_~O?ֽ [~_?O?mcc?-xp9$OCӛrQ$"HD66;t~905/S?᧩m|D̦vu$i\@/n91t<;ǫRΦ05Av/"vKxb~=] @ٷ'N'?=vlbEKvf$"]fp꿙xQNxFcHÞe{;!>$*ˡl_Q-,lQ^IL^?ΜyvG[_v9kfigf,V;3%fPOj?ZtL{UM3~}}lǺՏ٥^ Oe/pO3?bU6U_F8$*v3/; $/i\gV'$}qFNp}~J&k˒7ILdy mD4rw}cƣL;!Q~C/A㛉,CO\/L0qH ]I ԉ!$-;eؗeECEź^ g .V0_o&O2X^t.\yJ`7G^4Bhzb*T^ 5\zb$z'^uOp! ʚ-,h#Ե^]K;Ћ/u{I\tǛa9|Eu2ovAW/c!O-߈k|T$2gAaX|&f;<;4|7M1j#7|Ʉpҷǝh_L=P- 1Te鍊R^~虊ѥw*V{z襪ejr> endobj 88 0 obj << /Length 4275 /Filter /FlateDecode >> stream xZK_ >]¢3ck j+M. HSH=ǞH(;s3/^\r^ϯ^/]?y;p}5_}|= #oC x/TMzy=z2w{ͽa{c[^ws;>c^?z:[7?9!bOmtE#z=}u}wzOO!=orgO^~S۸.RV.M%߮5ۣ[HWn0K'ys{$1Vw߾mr>+߼xo__0ػ^|t?iݑ+ib΋:<:vH5zzjn<%|0Bc0S0s2T7StWn n 6O30Uzk&/p'[yc#- wz UC2CqhgC#)fqaG8;a [D_Gzla6(j fj|-*3 BtvddVV'M8l[nQA\:n‹Z #eb9"3nc9n¨=vGuE" cDm2%}fv0'"pJyĝxq#zut{cdNJIV=d`X3#ZY@;Bxڙg [4=d[2VQD( :}s#G aw p>@j1ё<G2@e2ҧ n`^˓1z- k npF@**σzUݹ!ਗ਼plg!'qaጀδ`6`0lTm5_oHJ26Z_τ:#cƃ(9bjCŤ?~`g=&y(" [:rDo׊GY O|7?^r#6`~ RO<]ҁbxݤxyv>f>|1_W>5XVL|%!;_WЕ(wuX5bE&ǃo[(훏@Tvp8 Hv*u)ZY7mE ߶bАKPÌem8P,-%a B"Ǘ\Ma!OddMGhם{~lxNj㡅{}Ya»H9Ltvx/akw'I"A>SD"쎧hՂ0iyVm @ O/E- `8<>&B!qaB>8,È7iB>4@!OS1|Ha Hȇ'. &,mOH-yH^-ku6';&Ifæ'&*ux f^j8ĊO`1 2lQO,aD'Np?b i/~25+7mI1?e?%M;ua/~ܸ l}##EXRK&|hlzOT{he={ 0нxZⱟf_]xx-6g)OhMckkD{*zAˮ'u\@^ѮG=ۮwEv=㮗wmCQiPfk:9m]g1mySO_6zmƧW?ǥgouGzxJ𗶞">nE|Suo–^Su {@z.D1D0)E"RO/DdlֻȩzY=M~mn#'lj^Gbz|N=>l6>z^v iIO_sq{Uw[ l Yn"B^ڭMfnK f2:J8m:wvOcA?isFP6oyfF(myksLAް}lEv<P\_ΠdYR.zhrK63br*3 꿙xu('ѲC6]6mol'ن,^}E\2ݮGy%0y9 G[_v弹mkf4MNmSf%7ԓGnSUӴ>f|۱n~1؟PދϠT}cUr!V5i_ac$ QAxC3^v}r [tI^޳ )\gV'|E|P똑?qh&?UC îLu=m$z7^uO~xey4uW)m<^]ta9AxuSxeǛv;+q' okxT$2g╎AaXxvw]9;4c |d:s&"^gj2"\q;{ CeoTJ|Rg*&GAX=?Ӄ/U /OUۃoM>ϊnOz<\{Q/l=zb]o|Gzd^zQx>;g=9njG=Uz~[`;35UtsƗЬWEK>@<]z0"ЭGK 3ꧩw?V/=4w%;Su- c$&[wl#ѤCjPo^`˗4"[o/Wio^\zOp/^6N=tvpbjԶ^?GAKo*~%OkWw5~Ȇ'x5UQnYg,po{[X7yK_a!'=jLcx/>3endstream endobj 89 0 obj << /Type /Page /Parent 3 0 R /Contents 90 0 R /Resources 4 0 R >> endobj 90 0 obj << /Length 4158 /Filter /FlateDecode >> stream xZKfG[ . f$&-bĂXDi$}αա"v}TǾ7�~ۻ'ٻc66yJ~ʋ^|'m;7/z$Gq 7/a]kؓYo{}׺YZ|L~g}d _?|[p D'ۇ>E?}߮Z^/]KqOi&x{?o폥';&QiX>ͳkIDl,?~蟿7Wޯ~:[=~wlf $NOu?5dϡMݛLfj%"#M{zy3Ŧʰ2ıQB>TLLџ֧Ԓ2~./I$ԦЁSv!&8 "?#֑L-pV_@2m#z~2:Q|zz מJiuG 8fN^YHB2 Ώdfr1z-Syx$#OS_p L7\v:YDͫkTzIW}k 3E!2(YXi|5 U ~3%`&Ѝ TS tUn^FT^<FII=̋*-aʨ="ˈRM [3*q"G{,`ċ;㮣+= 4]Zie I"doiC`" q3Ё Y 7JW<0gW@lU&/L*_A@]13Q=x# KfF<ۘˌaLFqdFfa2,[#82T4_&# 3M{p?=O:CFg;!R5$C\Oy2F&Hu|>.d6`4mTmXH:6ڠ_ό#cpƃ3s9P)>fŮsJs0/A^v6Q~/H{ uKit>.\ڍGKZϠ,ޫluS5goՕGPqF b>|I1_7X#6_O `\|Bi?|y6_F<|_'ņ,rqt-YA`7QK~tDhR;UvHб^pf C^(*~*o~*U;y|VxݕP=Wݦ?NW# <^r4Y.I@8η"AE/ߊ؊%[z)&UuGU[(؄ȥ[ը[(V[1%Coʼn|G"XK׭h,g+w1~;@CnA S`7lkqRxRo!_܇[w♻E0uo__qwa:6] <*3{KO vZ^ _dݷ;wo>[exZх;)iDXm\E6{dcT2١:V(ry.! +!؍ik= 2"Yhh')!4Dm <'enmu*O)E_xg-6Nīa'@`W1_ZP64 <8!E|\dCiŒ|| e?W[HΗuCxo #f/'=x=GΦn!#N>Pȕ/qO]6 88V>+ g;7&wm_(|h q6( Gt W/>S.;:PS4/i20|[oZ7Ӧ_3_U؛iCz@`pH(Uohs}#zE]L9&V=vS/5]O}}zKۇ̬|?usfs%yKO_>z~3+37C"5ts壧OrMky=z\z0ZzI$^CzQ$"֫HD6[vˍz*zikv?fS:sai@Tk@NMM~j};HػvrZZ_v/"v.Ҧ9ztn1CNKGMie;<&c88:[6g-Eh3<6o͞Q:}eٜP iWH_.ұm ]^~A/+ ll4氻sHgm ӷԘq(Rwagqg%lC:zP||f"Uf [x)u*'ѲC->]6h˜(|Ň,QKZ}ƧlU^ L^?gN,_XlUMW ysHT;f3_?(^]Rt(ſթd6ggS2X?NQNb|-sO|(/m;)_)au|ѼjLg||Ѽ]dڦeRD&_p#}88i-DB C|iQ'_4**D UlE%QX*1xXZr9^LҔͿ?Ϥ. N>1|`$4(ݘzH2PWN;]N3_,>0m 0LXeiq\Lk\?;S<,=> endobj 92 0 obj << /Length 4234 /Filter /FlateDecode >> stream xZK^ .P[&Ri J${= %gc>>>ﯟ_^?]A*Q.z/z|#!ÿ|WG_-z9^zxeY{={]<ֵEz^w k}zOwo{ͽ><׏tw)!bOet??ٿh䳰^/_O=8>.wq=+ޞ|vrb_viJ,vDFbtD[,Nc}{sǖDPJy}o*߾#}6=Cwlzw$J7y#o~iy[h3zzj]L[ALaXb_MKwH>D LچԊ!ɖcgFkؘ1}޵ a3t6PyڙבLp?6#mӝ?ׁ|5ÝzTw9/X1W/pJBBg_p~'7ѫ}1$jeSe.Z5yB/Ej6_KZ@(]Yil5U ~S!`@ApgT)W{~V/HsNL8fXc<0frϹQy{X"mxoI|oi~^s5q^܈s^pX!"cu#LB"ɪ k&3xDX3 hG\;cx a}K*L9[TDr. p1z{D1:H-f\":2!Xfc0BW#T4 ]Tdy2Fe2a- HEy0R1Qс;Ҡ3dt±;_51C|y/(\ß PæV<[񂴏g+AR`)ֈ+oo>QEwɆ,|pilbTˍN&Ny'y:JtWڭ"AZ56?K rT []hKGyGfqx󤣴몼.?6.7~V} lۢf`&':A>|:l\dK0j1 <6TL#Rx}|6aɪKB>Gx" zhh$PO^]kʍ$pa_`rǓXk~~DKP ^k MOt Q#^>n "tu6 o{9ԉnsƻ'x lloGukv>vV䟙ςBC΍ɝ|@C1'C7t&xm6|0%L>MKɧ ?V5i_X֯ ؋iCz@`pH2.Qohs}#zEL8&nv^wz =F=mCQ~UwhǴM=Ak 7G޶^aaשw q!)C7_zO=ֽ [z7O=-[dEa]J`1s1%̿j.ysۆriR33,LiKn'ݦ<i}>cFbr?AslGSbǪgCj҆4 H3]A)7C|g>@'蒼gSzN$|1#'~x>UI1ڱdrv(k3~@&~nXN:Nu(SH_juPfb? j"6L;"qg~9ҦVA$-;eȗeEOdR:_3qڈ)Ec7@|i,/:웣O/O4>0||L~D/ ]zHh:t7M1j#E|dDYw*,QqO>R+eJ]|b!_^&*|̟ݞ|MxRQh^z/6wף|wzs:%Վz(vw;1vfkƫ/ۡY5ٯ0|zxb6-maD[=^!g/OS^zhKw㩧?[$ꧩH$M^#CϑOGIԠ >/=iDTT_,=7(S߈>un.=M_nmzjվm^GAKo*~%OkWw5~Ȇ'x9UQ~ݲ"X&n)snĿnv*E^}|}~?<՘H?~?YOsendstream endobj 93 0 obj << /Type /Page /Parent 3 0 R /Contents 94 0 R /Resources 4 0 R >> endobj 94 0 obj << /Length 4211 /Filter /FlateDecode >> stream xZK^ [^=-J4>PT9A"gc>>>S_>y|u۳e4Vrz~W۷GϏ_<狏xCxOxRy/4M{reٮ0zuX~a^z{]-_^<{zaq~ÿ_}~㷿O?=%_L,7_ٕ|w/?nEޞoze^~S۸߮ZVޮ͈n5EeH7m0KR'X^{$ _Ig;ME߽vV_{O.{0.]s^q㑷l?9)^>[uځlWؠ|}]-?lAMeXXMKWU!|AnLޮچԒ/Kg 4&zI׫V :l|~'brWv_nWu$S ܠm:Ц [hH1<t'_#~_ϫWqOuG8fN^XHB2 Ώ$0cj~I#F؟Wq&t ̉WG/WZ׺g"BtePjrGfJ}[B7PN1)W{ SyqW+'f49'^&p,Y6Vhə FM9K,L{/"DoRޒ>7;W8%_g5 ܼ=:ñ@ ٥ۉP !Xd5B Q@j1<G2@g2ҧ n"˓17# HDE\oWKΐ FTM8v0ד8ʰqDAxp12l>F@jgm0RK=lTmXoHJ:6ڠ_τ#cpƃ}9P)>fَ}Js0A7lk#'^r6 )m<;υ\鈍'حxdt൸7A7I?Ǖ/ ʧb+ߊ+흏$bk |\b.>KF,Q@d9ҾD,I?&F7gL̃D-y'y:JmWڭ"Az56?K rT _]hѶqT8f$}+:= |)b`)z{e]C1!̏;j+RCME&DF`D\@"d>ȡ({)N;)NŚ.E `1>Kf'4Vu jRa[K̒ٓz >\2& \-9Co~|>[Qv1OFMG?+$z;n>0]8&:;[wo[%xZх+)iDXm\E6{MdcRT١84lت M<(Hxq$iI mII;=H2ȵ pMI~&vPX 6iEARǓ0it*'ܻ(% H DMvXH|EfMQTEd$:AXdNDk/! r](H2zZaw%(4߯hb7چe.PDHdI$qP+$DK]y?' Gx" zhhPOQ]Shƍ$pa_`z ,Q6h|(\wt,gєOM|oUi]|L|~M>Wq`/ !ɬz_GY4?z3嘸zG[uCYvV=-mzzLۇ2^Yiz3>SЖM=Ak W#Oo[0~ЏK0;zxJ񗶞">Ŷ"z4aKv=v rhA^ă˩'xz oʡGK"D.=|.7ra$C/?ˡɯm|&MHlCσϩއͦq5Fϫ_@Sݎ9m66nw aC?{"k~7_Dkɱ]Msp]c3 iLc-N1vx 8(ppt6m[Qc6{zD=輵9isF6C7ls]|*u5lvDo/gPHv,z\)]`c 4\D:ku^;;}K.5vb*ݦ} 17hUag`gFZ\.ReaW> gl?ƐD{FM;S(&3'E]hk}x,&uˉ13r̔6ERh1lj6njc;}T?ޯ.=3h?-x>(_XlUMW yMcHT;]F(mȉ,dZܱ~,xĶ/JvnjP_ha7SNScæ?ʔ {E:u|3zIEvi{O;"239ҦVA$;uȗeEOtQ_9f\{ȿLu gR&_t8%p7G_4'B >0 ||\~JC]zH_A_?u(m<^]la9AxmӘxeǛv;`+q'O7ڵm<3JǠ0,XBG}3,\f?F|dיW>u|g9|`Z|A`n>#R7_~w^yveY {𭁿yY״Y'U`|O;v9ꅯ]O Q}+Qϸ;q笇{$tA-ڹKO:խ7-K ԫ7O=y.GKwח[/wzz;|xoj[񣠥7G?P]~'?`dÉ(?nygq{&nsn4nv*-ocׯϫTIxg?_|ΧO endstream endobj 95 0 obj << /Type /Page /Parent 3 0 R /Contents 96 0 R /Resources 4 0 R >> endobj 96 0 obj << /Length 753 /Filter /FlateDecode >> stream xVMOA ϯ·ww *P[&RJS@Ig<*B/l{9XuEm-l'p:SFcN)] +V vlD؀ QID|h sPp֣!|APDK/Uf}C%lTGJX (Xg{sc&+_S}17 Yѥh!hoHƉCK"81f1{NSbJORURCO7IcD -wܥ`) ShhѥhxTF<\FK L3K?ŗ-:5׀E#|GcߒyU/^[мm6]:lOo +hSݞw vgNIKƖmHxA@Ub/i #1y> endobj 98 0 obj << /Length 3636 /Filter /FlateDecode >> stream xKWi]5%PRqbkZ{U}"|[ks咖o_-?.XֺTמӺ^tų۶n۶_7˶떖/ ikkICVԖ˳Gi=&޵ux =𮽎ճ}l/u_6G^q;1`ߍ1/=1^}{oӒ2R<X>?ayn(^{?eۯx{>0Go/Gx{9*kɔo?ηru|T{큭3>޵ݿHR,w/ݷOdq?]|W/~xOYa+=sgo~~Wo^w[L~Lֺ g3]<3ܗ)cm;:68¶ͰǾ ttaXf~zxka.n qDm[58Npf-;Ճ9)p-9i;$LCie?TSp"cHޞ׌qy=u_ۺy}m6SX;D}wo}0) z\y0~,OLf\ym~۱F_f󅉭 9ͯocfI0j6g)ͪ6ץ[&aTBJ7I|zBYDb]Oɲer1:b nQGeQ ٻĉxm3a0#\O'7iF<z!\OYxțE<ȈГex#xp=qI#{(F䣅 ɟh0b.`J#I l'T'~$^x='G"OjEMjSo5DKO/X!,1ͮ'kA DR0M#i}'V{\he>硿Wy}bG5Śo#xX)z<$ңXzKΧŊEx+ނg<bųX.OOH]t]tX~).z:V.z:Z.z:^| /z:X&x#qgrәg+f>+_|.W=z@\zD7ĪGUOq>!q鬧墧 _t{bՃbՋ_G ]tb_s?< vS7ۺQFVn egNݷ[|$ ߼*<]`>L+; \!L[r(}ngZQ3EN.?C*~\_Rv^7 >3< þ'7\u±;W5ߛUޝH9Y9((^3|XyX8n3yg\خy0;38lw>K5پ~vTŹZ -ٙQiV.ܜo&nuw$eÞe};La9mvWv;\e:,-Œ'LqT.a̮g;Θf;dgfdnvfJ|0W fKsF}܎M/V.-WX?f?c9W-g/eY)9t yb=]뇗\O^]Rwtf\e~E}|qFNp|U6XV !~msnn9 }h&vp>g.c`XgGrH[,=3zE"vI Ilcക.ж܉-JW-x3k2R'FQ'I[m([U` *$bpƇ}X'a~aV _Kd?Nyz'gXks>Ě/oCk=z<$ңXz zKbCIx+gb{B,? ~#WbY;P, ~*ߊbbX x XF|^z@zAz"xz^ X8_⬗ĪĪĪǂg&V='8AEIYU/zW.~qYO;vl&_U۱{Tm=vkte_n#磶ݪ4{U`!?.o$)`"~z7Nlendstream endobj 99 0 obj << /Type /Page /Parent 3 0 R /Contents 100 0 R /Resources 4 0 R >> endobj 100 0 obj << /Length 3459 /Filter /FlateDecode >> stream xZK_1KXd2ӏ-(HĖ@,qm96ג ,{ϭofqT/p|qJG3#txH 7Ϗ?_>;>pu'-񿇯>_pSj>0%\Ǔ_Y:Ϋ}@ /jS;s2ʙ4'tV>熗ӿ>߷^?{#D% +nx$˛??_X:/~yOKzT՞隅 2kޱO=Wg fwKv; "[B>釷 t5kuu|28 SO<iy,l`[oBC}A,A\O \-{0O`_ "QY>H$| a\7MH._E"|=X=DTAU# zͅDn ⴤj 5Q،O oąo|~J!q/z1֮/lJߟ-Ff|55*v|GIr'ܿjOtw7X6b~[jqßp{@<4GJw`z]!P(KOqz g}QrOtk`sL= xzz878Q;ezT N"w'>H4i$U6`&nXJud!BE2>!)#2"ˇo3ohylጳSK#gs. E+ǡ>1b{sƄg_u/9M0as ϢT\i, &8&Mx:G(NtORT\i/\02ïz+#&{.^p6`af7_/<"M:6e45h(P - RHc!;|3FqŲ0HEO*Si|ro&m39OMє|>EhEO"SD=D=_/a'Cܮ{>Al+zj_-60 nN~`-Z!-I8\;?ɵ)qIO&\Ow~hR|:D¨O"O"e AۖOv~CWL L/]5bS{m Z$jx"98R$GսŃD]\8}O$*x%|hVf5߀[vD>_[CYBz`^1'^X\>X=>miBW= MV\(OQo!x1_Q->4.;:V\c(_|I+20|[ }hU>&_3K艭|O !1>D8o7Ĵ~D_ -Cb q/eLOY%lƴC{jC4~KO_HoG+ƛNϏ`z饞|z͡OXC5z#EܘCIC7Q"(ի(Dgo].vz4:]+OjUSrz|CuiIvjG `iӷ@oڕj[1^,|'iu>0!qc(L^=/]_Í Qt}cB?B&ʵh ҐONA "xdL,l&.p!x^h>oS]gj_Fi=2PhZ)v"zNꝁ7$7R`b@H(MGGb|$O>K]>.*}eJ=_OSOM'h|O|~@]h_W?o֯\?9~!r/iBF 3gVfr~rZ>!@OזMot"HG8P| RjC~U/ޯhzG1E"Dz㌥w#Dӕ87brՓ4/T&oUxJ8_:=]8hzwڦKfzxGz0ڸ Ey߸X%?*[|X7(;ߠLK=8/?yo^}E# endstream endobj 101 0 obj << /Type /Page /Parent 3 0 R /Contents 102 0 R /Resources 4 0 R >> endobj 102 0 obj << /Length 4204 /Filter /FlateDecode >> stream xZˮ%G߯8KX#뵵H@2bd{Ydcbܸ}*Y'>{Wo>}* j1{YWn)_z}?ק_'~V^|_^ zo|n__z|bOs=^m{גČ@ɂM5xo?7{o.{f&[̞i\q㕷l*omƔ<^6ɋ+q<#pjo!ܞx\jӘZŏ$a8 NoLZO1A8b1E =/ܞj8ǵ,fpi|81Nޏ<,WZ + ϯd_Oz q{O0{8WI\仈/\4{`#R3jߡNJe\(Pzu"`WfXf7 JtpHe$:'!t)!@:4_rd\ f܋$O\EMBDW;wPC<|u@"D 6ZPI&@?aCH5oXF+O_/L=yt)-*IA8u5 M*e(U3BL0#=TLU R/"=y pv0tF-m9imda+*\+ y}x0mt1LF ڱIpZFEH\0ib}zX4Lu 78# â-dLn˘$k'%3PC,,G,L >1h)1DXMO\|ٻ?2Y fmb`Q6Ĭ20("džm+gm a?c~Qr-h<ϓ?VG֋;^;g|?zR|bƒOE|dw GWb#ϨGV=<$p(m"؏"CClbAEУaثXs!+}dh4VIeaMLp4]Nx O\v|WuW!&ϯDzJsU6b,d>c\u)7y]ڛ|*Omӟ'-&~itI:+[~%v5<djb<|ܔ'g~sc*C(E Tq*G;X$SSp&%FS9RvuM& `7UJl)EioNQ: A$9 0WzPב7$*J|S|S3D>;L%O&nTi @n3o 0*]~6ubvBg"%na*s } 7N-MHChx&~=k>0iRgޏ+_`GD8j<ǞPjmo` ,?fgՆw˟]-w;E'^O]-҉7*|cפk!N<W#ϝ~ ;toڕC|qX}xo> p >#/`泡x8|o>Rև/x)0?cp\k`97n}|[z7-GS2+b,t3 WṟUsPGPhfeV^k`5vpf\SfqmD~^ŚSQUvJ“UXZ"\4fjdDLZDy&*'-sdJsb)9IWw!AFΑN.ިqqbz6/D1NEIhub/e8 yb}~N(4c(x(L}-vI$LFT"vD$Zg"CGԲp쟬OF-YLbS,bb.'F`ēpԈ0ą0ư7Z^šz^/,p'2b61êz-Q#Ѷ}dԛ^`C>|ړPh|`Y|²75x|d W&w3C>_n͇Om[b6.=fjf= . m]U^}3'zGLA!1U/ZO=YV}ؘzL״g˧1\~~r|RSo K+l !aSS,D.=7"v5r9bIMf S=zRћ̧vQˮ^UgmT]?O|~z|FlmFw M7Kϓx>[HN}5V_#Z|OzV߰_endstream endobj 103 0 obj << /Type /Page /Parent 3 0 R /Contents 104 0 R /Resources 4 0 R >> endobj 104 0 obj << /Length 4318 /Filter /FlateDecode >> stream xZI].\z$J"[ Cl:=9( gSg~xvNJ>5\;o׷oOO<9w>/ך?|<3̓??+w׫”r칿ۂnsypx;OiCF=;Zp?|GHdݿywoz߽@@OG_y컗߽~_Xػ_|tNR;r%[p~/c#SY[HՇp~"R'kGNz.Aںp#cP>% '?p[ad5a|?T.C섣3-]wz ߏڏz"ԁ=1X^af&ρm=3ޗ Q勻{tGO3q· +0=ĕf1囿;Ѓ2Za;b 0 !rw>mwg; 8_+lmzCKEQ3ADG@,Dm#9S X![!4=J0U6$ĢJ )XT ߛ \r^3-(ㄌ%A}(%[å[Uj6j3zAfh"He !Do,XYa*WtB(XR5"+V)#"B% Ar3wcP)3&Cv0HC?0c{,-p4 qUV+~!w -E ӺvҠ8-" i84R\,jHD2hG ^n2&Vm ZsĒi! fdg#[و`{F؊81DX ]b8s7[0Y8oG`fYFم8N8|p g>_2MF*/1h-ϓ?^}'Y\89~7= vK^'>F@od9z K`o;%w|+k||C ;Ȣá.`?2< }TA)m5''OAF=h9Y]$6G‰Q<]>Q]Y|6ҥYG]$NeMo_UU<.ftdbl]щQOw P| K;q8oCY:YD >2 MY ea-ӐK#߶̫*[bXE|[FV閙Eu~bubuXI?d.|`"8e42xop e:*Cgi-hؔMg"^>}v0ɻz2>h"*VK?W=uzh^__&2D1=#%:ae::$ HZ!W_,&tF2`bH/YF1%~D򑒄Er* z)O&*O2pb&a B*AHOLf Ƅl[L!|LpGe ~`(~*Dj jW }gLD>yTh?P}bē0䦿2D?T9_/* 2C#rΖ҈V4ӱ^UT)_`kǔ>/0uۣJ"l{UImO(5Dz73X:ϦlIxh"/ߊil:IU[-b9 s֛#]"}+blt3 gyYS q9Czy)~ˡy^ۡhvS~@zEvIlIRM=[2ʩgԻgoa¡OИzCxMzY'<;z}n^XVg6kƭ*&kB66?o&,֜QVVb.Z" HHėWMl%crvǑEHD FS#G skk "H j٫Y`hcH1- :0'#Q)\,1h1G0hJ,P(<#Pt5ltlJBDCuH^<sV9$pf"ǁn#8U"3,FO҈DiCaj#'hEc$LDQkdL!bOY|D Bbn`ϑZpL2f(lIbS,1’(,\F'ab[anbkq|^+,p;#2bi`6EΛFu GR SoZ}+/ d#l |h5Zӝ /Giğ4ۣ&E#_b5!5uVղ޴:3=fba;7#VX(+"F5f̈́#|dč&*DDaZM(\{o3+=_vٔo)=ڕ i|Wu,ich~imj?t,HJb5fʈw-Bsf͋hp4'μC8sbBB75J4=p`bS?QT{ĭc8orab^N{';@ǴwrxL]Z;MQ+KcxݜkSy6R7q3b^񚼮HV<`W3SnC v5wl g>%7=_3Q}k v;f_w'4->HQ|"E')kߤP|bA30Ϸw)`!q/nOɷl\&',&n$>\|OkwHz}כ4#w+/z])g=$f6%WʮiԷYoi6fk95Yl g?\z8zcc1#?> 1gݡw?C3S/CO1˨RTcq>c|Qz֋ġl=|aMS=h^UŭgoN~z.<4@^L=TSo'?"d}7/H =FkquW9y_?Z|o~zV秖Q5$O-_~|}~|ًokt;8w,^z?k=.fendstream endobj 105 0 obj << /Type /Page /Parent 3 0 R /Contents 106 0 R /Resources 4 0 R >> endobj 106 0 obj << /Length 4298 /Filter /FlateDecode >> stream xZ]ܿKX%PRqbd3؈~`$ Q{}PO/}}}vNJ>5\;o77'Ov]O> ߏϿ>_?<;~S[~ւk$>8E$ }ro^<巯?z/[,W/ylmdWà\I~˘.8TVR!ܱ_Tɚ;Ӵ!+pK.\X.Tr{dw‰ŏ r8>jM;Lyݵkwcއ(u`O ~qýIs`+'#*x[eC~%L\|p?k em?pqY |N6 F&D5 BܝOA0#YNz׊A5@oh tf7m:' t!d !@:f_g\ F|7 r߆XT ]!x {S+B `Ջra7%Xd B|tB_FwsP;_/ -X4)l#$ՙ0pK7k ,\媙.bWKWFb*eDD[$$Hnn_"&<%{/)~_\y{bE{"ioTG`OF3A;^zSwn9Wλw3(#J#||D8}3Ϸ0[|,:0bc/3XиIef:ߊXs!+}>iԃVIeaE as4q:(@ӮCŇ/@5xȇ`CCژK(:ĈI-P&.x2 @Yd0m˼һe 鐉UķednYT -&[L-&[%C")˗ F /`[F#0a- H[R8d|26MYڄ|.ﳫ\mUOի1@PQWB?>x/_顑{}U"^f8iKwx5wZBMh|j9" (T=mi *Xjp`i1w` )O2MUT R()脕b`.@v#k=\~"ˈ΃m9"Xdri/6HΣGJ$3<<ʐC‰33?b$e0!>1%al2y3)Q<<Em' ]'1fLK R@Q܆ ֋%oOf? tb_P(~&$7˰9[J#>Xi`b%L:a0sBUVc[eՔ ,1 1$W("_ ep{%"dO{2> TZoluOJd051tNI1oCRDs#?90!ꌼ a*E?#]/V BR3&%FSRveMd `7EJl*EioFQ A$3"*Y`/7*<$#oHTŔ+&+93"oW*0A FsK3oɱ 0*]~6e`vBg,%P~eZ|ۘ-zo@~ bꯩ7\z+3;z"m%#穧z-Yzo}9LGaA[۩'忲&K5ox*EBcia㡷FF[79nf9F{5 `GlcZ۬q:\JYy7Q>wf}U +PvWhv/GrVGG"-8or`+; ? .rG" l0)O=B^] \%G2^P^SDF \iс!=qJb@-%%9A[UbiBF1A򦫙 fSH'fkxL?0=W"bDň:0?OPY&408wf1"~Fl$J# S9iDK,#$do&ΈZ#c*{D Zg"Ct{Ԣc?60GaK2Rfay$Fa2bF<{ w[eEZ!`sȰN1,7v5>FV8z [yiq'`#hWC+?њ4-~Xx9L#xA%Pe6/ OŮˬڬՑ6 ޹?‚DжX!4B$1k&7Cx$%n0Q!"?% jE:~#~ '&^2 @Φ~KLшQ7wծqL*ci?MGC#KmScyEP1WFk|4o^x%uEc|פx=qOġKQ%c}q廉%nmy+8 { tKw_=2>clo^xH^c _#ϳR.uE95v3R+/Kdc8)q0Uw8;_S+ݙϜ5=٠iA)~.>IXc5&E % ymKIW[|pK|O%f28٠g5q;<%{b5^Em=ޤi^}a3'zGLA8!1Y/yRv=MzK1XQiw='fc8 '\ GWL=C"zz_FMEO=ۥ׈u%5㛍ԃ^$eIK[o2GS4=7/n=}]/?p w硧jĆ&bdqրz|C}=<!Sxߎ~D17Z㇍0ϵZS7F+7?m~! ^<?V5f7}o_sS3endstream endobj 107 0 obj << /Type /Page /Parent 3 0 R /Contents 108 0 R /Resources 4 0 R >> endobj 108 0 obj << /Length 712 /Filter /FlateDecode >> stream xVMO1W5]WPJ4+8TiZIE~ǞD.K̋ W`5j4Tz)byу2h:;s g>N3dna'n|ܞt>2\al [3Mڈ# z?nulWlwއ1 xZK-Ed9ُkk׸S7-%SK)}ݯV["_|v[.?tG)Nwfc)8G̗ˏ?w)U@bC"ĥl5y$?endstream endobj 109 0 obj << /Type /Page /Parent 3 0 R /Contents 110 0 R /Resources 4 0 R >> endobj 110 0 obj << /Length 4200 /Filter /FlateDecode >> stream xZM^ ?.aZ敺@,JJDRѿs } ę1c>׷/W[ҨwMxt/z|o#!gſ|WWG_-z3^zn<ֳޡu7z ևyku7^oM{ͽ.0{}xigwO?]1?_4Yqӛ#ӷ?>By{Ç2n'O^~S۸.RV+.M%߮5ۣ[H7n0K'X^{$1Vw|ϝ$@k_~WG߼}WaRw㫷~ݫkC'ӽy(NSU\I9/~˘jZVRީ^)Dxadl0|0Bc0S0s2T7StW|5 3Sa"bwؙ[l=6B rG_wAQu !>$ 1Tv_bhwuZ" l; 8HGt'xk|^y*~nPϾ^) ]V^Fd 3Fz wupv_?zla6(j fj|-*3 BtvddVV'M8l[nQA\:n‹Z #eb9"3nc9n¨=vGuE" cDm2%}fv0'"pJyĝxq#zut{cdNJIV=d`X3#ZY@;Bxڙg [4=d[2VQD( :}s#G aw p>@j1ё<G2@e2ҧ n`^˓1z- k npF@**σzUݹ!ਗ਼plg!'qaጀδ`6`0lTm5_oHJ26Z_τ:#cƃg}P1>fYI} s0Az6/x6 )m<;υ\鈍'حxdt൘7A7)x/v+_@@וOE=V;AIt38$|]|bX|Q".>J#ϳV2jZt[0lh/:Ȓ&vI8+db$؊w8QDw kg<,1Ql]v-q/>卶Տő61k'ϓ"0_gY-mWܚ̇`o@S Q=_XKr(&U1GmU+آC+^/Pb({)N;)NŚ.E `1>Kf#4Vu jl vö %ճ%|d>L@|5@(Z5\zz6psՑv1Ql2dM&L}vʆz=Z&)?5;;,?e{||oejaw8JMafp) :oE4 J5;HaEVe08ـECA‹ I'H(LRLhKFF APV+ n%tMP+ I lҢ yBHI K$icvQJ" 6!t{ @v(~ d䣨&.ILuHPD".~tQREAw'!vv^BFMF۰lQ=YhhO1qP-(3h+~O8" nv0R~Mm$U|HD6'I-yH^-ku6';&Ifæ'&*ux f^j8ĊO`1 2lQO,aD'Np?b i/~25+7mI1?e?%M;ua/~ܸ l}##EXRK&|hlzOT{he={ 0нgcjpj<b-Ohuzx-67I7S;$zċG<ٍ?wAcOͦp&ѱɇ)|I3'Ju1mk55\{=mU Ifea: mzDYhף m;"qK`S[ҶǨǴm(35O~?3혶^'/z Aƶ+37:#n=D^z6T=~Mu;٤৯݁*ϵ[ l Yn"B^ooK f2:J8m:wvOcA?isFP6oyfF(myksLAް}lEv<P\_ΠdYR.zhrK63br*3 꿙xu('ѲC6]6mol'ن,^}E\2ݮGy%0y9 G[_v弹mkf4MNmSf%7ԓGnSUӴ>f|۱n~1؟PދϠT}cUr!V5i_ac$ QAxC3^v}r [tI^޳ )\gV'|E|P똑?qh&?UC îLu=m$z7^uO~xey4uW)m<^]ta9AxuSxeǛv;+q' okxT$2g╎AaXxvw]9;4c |d:s&"^gj2"\q;{ Ce_ߨ')ǕJTL.S?Ӄ/U /OUۃoM>ϊnOz<\{Q/l=zb]o|Gzd^zQx>;g=9njG=Uz~[`;35UtsƗЬWEK>@<]z0"ЭGK 3ꧩw?V/=4w%;Su- c$&[wl#ѤCjPo^`˗4"[o/Wio^\zOp/^6N=tvpbjԶ^?GAKo*~%OkWw5~Ȇ'x3UQ~ݲ"X&n)snĿnL_aendstream endobj 111 0 obj << /Type /Page /Parent 3 0 R /Contents 112 0 R /Resources 4 0 R >> endobj 112 0 obj << /Length 4169 /Filter /FlateDecode >> stream xZˮ]Cd5%PR&؈~֪ꗍ`[w?jժUuN>+;UV4]%59]]^/\>y;p?|w/G>ÿ7\{ ;XPד]w[澞jK\ׇKIw0~qo޼|oy<+&gxrX/zjΛ=\~Â#\*zw_͇#a%]Is}ɯ'z\ sdžsUD*ُ߿} />+g<߿g2Ap߬ i*"Q`ľmΛ|XVi-SS~"ca"0dLfzc5S.w{c2S^LBp?8y]D6@/3Lv@\Ɓ@<GgQ cgȨ 02M^Fc# ,42ܕ@aa2FȒ`I!$nsFF',R.CF'?d&j W.i! '&$!gôüHއMxNy&ڍv|"Ul6އџk=mV~`g=_q:bx8o,GVU63jm@v]v-q/卶Տő6kPLpRTx*26)PlpX܊"d>6ފD '[کX׭h=P[f#ʭ8e+fUCQÎP-AΒd˲yDilzϋ硍{}YiZ N Apkxo_%j|X}<Ғ6id)%h6t01фS¼V/$i`ʳ!K7OdfWE-m$W_M5rЪDliK[ʖ5ߔ mM#hSnS6&ҧ,3Æ^Jy4m$Oic?,#sYdy,-QƔ4Iۮw/{/)U\.bS@_Z>N2Lf|Fབo4wi=mL|:d|0 < N^u'O2&+Yv$?H.{ m6GV֙ <D[g~(%Uɔ&G8o3~5ne\:xSZ9TG~hBlQ*DF:1/:)pE Χm:т8ޘ(xM꼞G܍_7QH||B^֭ *+I ~)m>ML/c7|P>`m+ڬϸ0s7Y|(KڬߓOy0?Vt s`n6q:cY/hwDжYWQ$]6Ӫf]zj9eFCzN[u{zvL[/|ol[0>m!їaSz"1v3Ϩ[ocb5s̿v=~b=ؽ~/Hz!zً^\zm] Sc;2zƧS/f[z~y$6~y LcDNmz|nw nKS$Hn!_,>,mͺv)K>&ؔMatK7sm Cڰ9%q P&ΊӧF5+_6{>r$3NlǬڡ4O3gz;hԢ WCsF?]>[Zޒp,I󠏚lm6C ^5_}C:Niprz-&y/+^^9u G9ᔖ턎 Y2k^)粕;_Sg:Snf]Km2{rpUq5Ł7INaeWk൘aLoėZAF9.V#u:Ӷ|a|2l/밑O;}ǿh _nrTuRu2Vj]hq/lC\'y8l$wr Ґ >t2(o&?U7]I~zr{=4ǽ_ڐ{dŋvO.,e6rA{ /ٮLU5.U77_-b=63\9AOi.Gi{zs0둭wף|wu^^_ GYovcƃzjkƫ/ۡYrǡ'kSO'٩Gg3S3ꧩw_ք|v~%{H[Oԭ/OSlFʇ#qP?NSHM軨IJbQo,J>%z[zwD/^6':tS_,=^S;z~|-h}VT_Os[+l8Zb(nYg̰y[>*-ki'X=!ߔ=I}{fs̎S "O_J~?1endstream endobj 113 0 obj << /Type /Page /Parent 3 0 R /Contents 114 0 R /Resources 4 0 R >> endobj 114 0 obj << /Length 4240 /Filter /FlateDecode >> stream xZK^ .aۙP[&R) JBI=Ǟ!H8s3Ox}}}zUU/ztIwNכ?׼ǷGO!\O>;>G>_?"/7Pn׫BUTדǻ-Xz)Z汮.<{5u7hSX<{{nq~ÿ޾ǿo~ {o+&F> ;z@ǟBy{/˝eߞ? v{oO >n_vrb_viJ,*Pm=J5|<6wևYʝ|=0[>NS [h%Ypo/w? !Z?R>xg߼͇_O?yx_ֆN{Pic#\piY[H5zzj]L[:6PLa _MKwHp\D Lچċ!ɖcgGoH 1}޵Ea3`6Pyڙבjp?T#mӝ?k;y.[s$^\A=zt_/,3tzv[ymGxy3.#O]_pF؉n~N\6X՚G/RfTόѕNؑuV9Z/[7fmFDt wFrn /j%b=ċcU:sɋ n&M/%ݶɈٹ )?G_wNō1"=Vw;1*ɃBV$Ycd(kqf!kg9pcl!o#[E J5NQs6ՀI1zWMjPHEA?`t W' ߰N O|7?^r#6`~ RO<]ҁbxݤxyv>f>|1_W>5XVL|%!;_WЕ(wuX5bE&ǃo[(훏@Tvp8VR;k-,ś"o[1h%aƲ6 Zb(fTϖKg0xjpzPUGצb'k2qg&G?+xh\V. _D&:; ۻ7YL-{[•I"}l."EA&ATfGT١4lت Q<h(Hxq:$iI mHH;=H2jjE$md5_"jep!)MZ"a O)IcI; p~bl.JI\$R~&$nnEo2Ql`|D"=N8i#(V. ](Hq$DBKvqQ袉h-j@' mMq)fu⢂6c9%efwmeI`S$͎')<T/O8E$xV-?x?aՆ Q RԒʰ㉎yc"$!&)9x&CLD|pM<ȇ&_j߯|x꒐iA>8Ȃ@/%/ɫebF$vǓWڀr# ܬu$DOb"!+|T ǓX0 "tA͡4 @%L~\GQ:ףtmZ/:ju~XK<,{ Zkj2^mo MR$bxvog /'=_xˁGΦNv.6=v>P#_``;xc=[[/&|wnM L>,6h|&(\wt,go'_&L>e`ɷi]|L|~M>h^|OBeCY/hwDXzCh+g1qȮsR;Xm11mʌz_g==L=@;x~>o ˆ^Coпm=  MNc[OSgԭ|MkynzH< [/ԓH<97УHDWl"m6tz905C/?ˡɯm|DMHlCσϩއͦqGϫ_@Sݎ9m6:ynw nSVB;Dn--t=Ҧ9z4®>C Ҵ'Nc|ӧmplڜ[Q1 q==tڜisF6C7l}]l=8|:Oz;T73(wv;YA;.^mn&ctjkp;}3a]jFw:NUtûMی#mbHNo`VV͌\ nGo&a]8 gl?ƐD {FM(j_XlUMWuyIc+HT;f(#]߇V]lt_/پՉ4d:fϧS2)X; QNb%|cO|(/m4)_[')ne|QJLg||Q]dچig$L5JڴqpJ6rW R 6TLxQXBА}&N0b5h CUf(op>eES}sTE3"TgO/OP+a]OǍW`3@Y}6B]UʵA|.?iCnx&^ghwT&^F|dיW>+u{@s|1@P|7*GqlR)~3T/>KUS[|"ۓiO>Wv>r [Oe>QWqz;Yy~[gQOޮnG=fbnp*O[Y8-e.6MnW?2~#FRG(E~_};O*Pendstream endobj 115 0 obj << /Type /Page /Parent 3 0 R /Contents 116 0 R /Resources 4 0 R >> endobj 116 0 obj << /Length 4169 /Filter /FlateDecode >> stream xZˮ]Cd5%PR&؈~֪ꗍ`[w?jժUuN>+;UV4]%59]]^/\>y;p?|w/G>ÿ7\{ ;XPד]w[澞jK\ׇKIw0~qo޼|oy<+&gxrX/zjΛ=\~Â#\*zw_͇#a%]Is}ɯ'z\ sdžsUD*ُ߿} />+g<߿g2Ap߬ i*"Q`ľmΛ|XVi-SS~"ca"0dLfzc5S.w{c2S^LBp?8y]D6@/3Lv@\Ɓ@<GgQ cgȨ 02M^Fc# ,42ܕ@aa2FȒ`I!$nsFF',R.CF'?d&j W.i! '&$!gôüHއMxNy&ڍv|"Ul6އџk=mV~`g=_q:bx8o,GVU63jm@v]v-q/卶Տő6kPLpRTx*26)PlpX܊"d>6ފD '[کX׭h=P[f#ʭ8e+fUCQÎP-AΒd˲yDilzϋ硍{}YiZ N Apkxo_%j|X}<Ғ6id)%h6t01фS¼V/$i`ʳ!K7OdfWE-m$W_M5rЪDliK[ʖ5ߔ mM#hSnS6&ҧ,3Æ^Jy4m$Oic?,#sYdy,-QƔ4Iۮw/{/)U\.bS@_Z>N2Lf|Fབo4wi=mL|:d|0 < N^u'O2&+Yv$?H.{ m6GV֙ <D[g~(%Uɔ&G8o3~5ne\:xSZ9TG~hBlQ*DF:1/:)pE Χm:т8ޘ(xM꼞G܍_7QH||B^֭ *+I ~)m>ML/c7|P>`m+ڬϸ0s7Y|(KڬߓOy0?Vt s`n6q:cY/hwDжYWQ$]6Ӫf]zj9eFCzN[u{zvL[/|ol[0>m!їaSz"1v3Ϩ[ocb5s̿v=~b=ؽ~/Hz!zً^\zm] Sc;2zƧS/f[z~y$6~y LcDNmz|nw nKS$Hn!_,>,mͺv)K>&ؔMatK7sm Cڰ9%q P&ΊӧF5+_6{>r$3NlǬڡ4O3gz;hԢ WCsF?]>[Zޒp,I󠏚lm6C ^5_}C:Niprz-&y/+^^9u G9ᔖ턎 Y2k^)粕;_Sg:Snf]Km2{rpUq5Ł7INaeWk൘aLoėZAF9.V#u:Ӷ|a|2l/밑O;}ǿh _nrTuRu2Vj]hq/lC\'y8l$wr Ґ >t2(o&?U7]I~zr{=4ǽ_ڐ{dŋvO.,e6rA{ /ٮLU5.U77_-b=63\9AOi.Gi{zs0둭wף|wu^^_ GYovcƃzjkƫ/ۡYrǡ'kSO'٩Gg3S3ꧩw_ք|v~%{H[Oԭ/OSlFʇ#qP?NSHM軨IJbQo,J>%z[zwD/^6':tS_,=^S;z~|-h}VT_Os[+l8Zb(nYg̰y[>*-ki'X=!ߔ=I}{fs̎S "O_J~?1endstream endobj 117 0 obj << /Type /Page /Parent 3 0 R /Contents 118 0 R /Resources 4 0 R >> endobj 118 0 obj << /Length 4169 /Filter /FlateDecode >> stream xZˮ]Cd5%PR&؈~֪ꗍ`[w?jժUuN>+;UV4]%59]]^/\>y;p?|w/G>ÿ7\{ ;XPד]w[澞jK\ׇKIw0~qo޼|oy<+&gxrX/zjΛ=\~Â#\*zw_͇#a%]Is}ɯ'z\ sdžsUD*ُ߿} />+g<߿g2Ap߬ i*"Q`ľmΛ|XVi-SS~"ca"0dLfzc5S.w{c2S^LBp?8y]D6@/3Lv@\Ɓ@<GgQ cgȨ 02M^Fc# ,42ܕ@aa2FȒ`I!$nsFF',R.CF'?d&j W.i! '&$!gôüHއMxNy&ڍv|"Ul6އџk=mV~`g=_q:bx8o,GVU63jm@v]v-q/卶Տő6kPLpRTx*26)PlpX܊"d>6ފD '[کX׭h=P[f#ʭ8e+fUCQÎP-AΒd˲yDilzϋ硍{}YiZ N Apkxo_%j|X}<Ғ6id)%h6t01фS¼V/$i`ʳ!K7OdfWE-m$W_M5rЪDliK[ʖ5ߔ mM#hSnS6&ҧ,3Æ^Jy4m$Oic?,#sYdy,-QƔ4Iۮw/{/)U\.bS@_Z>N2Lf|Fབo4wi=mL|:d|0 < N^u'O2&+Yv$?H.{ m6GV֙ <D[g~(%Uɔ&G8o3~5ne\:xSZ9TG~hBlQ*DF:1/:)pE Χm:т8ޘ(xM꼞G܍_7QH||B^֭ *+I ~)m>ML/c7|P>`m+ڬϸ0s7Y|(KڬߓOy0?Vt s`n6q:cY/hwDжYWQ$]6Ӫf]zj9eFCzN[u{zvL[/|ol[0>m!їaSz"1v3Ϩ[ocb5s̿v=~b=ؽ~/Hz!zً^\zm] Sc;2zƧS/f[z~y$6~y LcDNmz|nw nKS$Hn!_,>,mͺv)K>&ؔMatK7sm Cڰ9%q P&ΊӧF5+_6{>r$3NlǬڡ4O3gz;hԢ WCsF?]>[Zޒp,I󠏚lm6C ^5_}C:Niprz-&y/+^^9u G9ᔖ턎 Y2k^)粕;_Sg:Snf]Km2{rpUq5Ł7INaeWk൘aLoėZAF9.V#u:Ӷ|a|2l/밑O;}ǿh _nrTuRu2Vj]hq/lC\'y8l$wr Ґ >t2(o&?U7]I~zr{=4ǽ_ڐ{dŋvO.,e6rA{ /ٮLU5.U77_-b=63\9AOi.Gi{zs0둭wף|wu^^_ GYovcƃzjkƫ/ۡYrǡ'kSO'٩Gg3S3ꧩw_ք|v~%{H[Oԭ/OSlFʇ#qP?NSHM軨IJbQo,J>%z[zwD/^6':tS_,=^S;z~|-h}VT_Os[+l8Zb(nYg̰y[>*-ki'X=!ߔ=I}{fs̎S "O_J~?1endstream endobj 119 0 obj << /Type /Page /Parent 3 0 R /Contents 120 0 R /Resources 4 0 R >> endobj 120 0 obj << /Length 4169 /Filter /FlateDecode >> stream xZˮ]Cd5%PR&؈~֪ꗍ`[w?jժUuN>+;UV4]%59]]^/\>y;p?|w/G>ÿ7\{ ;XPד]w[澞jK\ׇKIw0~qo޼|oy<+&gxrX/zjΛ=\~Â#\*zw_͇#a%]Is}ɯ'z\ sdžsUD*ُ߿} />+g<߿g2Ap߬ i*"Q`ľmΛ|XVi-SS~"ca"0dLfzc5S.w{c2S^LBp?8y]D6@/3Lv@\Ɓ@<GgQ cgȨ 02M^Fc# ,42ܕ@aa2FȒ`I!$nsFF',R.CF'?d&j W.i! '&$!gôüHއMxNy&ڍv|"Ul6އџk=mV~`g=_q:bx8o,GVU63jm@v]v-q/卶Տő6kPLpRTx*26)PlpX܊"d>6ފD '[کX׭h=P[f#ʭ8e+fUCQÎP-AΒd˲yDilzϋ硍{}YiZ N Apkxo_%j|X}<Ғ6id)%h6t01фS¼V/$i`ʳ!K7OdfWE-m$W_M5rЪDliK[ʖ5ߔ mM#hSnS6&ҧ,3Æ^Jy4m$Oic?,#sYdy,-QƔ4Iۮw/{/)U\.bS@_Z>N2Lf|Fབo4wi=mL|:d|0 < N^u'O2&+Yv$?H.{ m6GV֙ <D[g~(%Uɔ&G8o3~5ne\:xSZ9TG~hBlQ*DF:1/:)pE Χm:т8ޘ(xM꼞G܍_7QH||B^֭ *+I ~)m>ML/c7|P>`m+ڬϸ0s7Y|(KڬߓOy0?Vt s`n6q:cY/hwDжYWQ$]6Ӫf]zj9eFCzN[u{zvL[/|ol[0>m!їaSz"1v3Ϩ[ocb5s̿v=~b=ؽ~/Hz!zً^\zm] Sc;2zƧS/f[z~y$6~y LcDNmz|nw nKS$Hn!_,>,mͺv)K>&ؔMatK7sm Cڰ9%q P&ΊӧF5+_6{>r$3NlǬڡ4O3gz;hԢ WCsF?]>[Zޒp,I󠏚lm6C ^5_}C:Niprz-&y/+^^9u G9ᔖ턎 Y2k^)粕;_Sg:Snf]Km2{rpUq5Ł7INaeWk൘aLoėZAF9.V#u:Ӷ|a|2l/밑O;}ǿh _nrTuRu2Vj]hq/lC\'y8l$wr Ґ >t2(o&?U7]I~zr{=4ǽ_ڐ{dŋvO.,e6rA{ /ٮLU5.U77_-b=63\9AOi.Gi{zs0둭wף|wu^^_ GYovcƃzjkƫ/ۡYrǡ'kSO'٩Gg3S3ꧩw_ք|v~%{H[Oԭ/OSlFʇ#qP?NSHM軨IJbQo,J>%z[zwD/^6':tS_,=^S;z~|-h}VT_Os[+l8Zb(nYg̰y[>*-ki'X=!ߔ=I}{fs̎S "O_J~?1endstream endobj 121 0 obj << /Type /Page /Parent 3 0 R /Contents 122 0 R /Resources 4 0 R >> endobj 122 0 obj << /Length 4169 /Filter /FlateDecode >> stream xZˮ]Cd5%PR&؈~֪ꗍ`[w?jժUuN>+;UV4]%59]]^/\>y;p?|w/G>ÿ7\{ ;XPד]w[澞jK\ׇKIw0~qo޼|oy<+&gxrX/zjΛ=\~Â#\*zw_͇#a%]Is}ɯ'z\ sdžsUD*ُ߿} />+g<߿g2Ap߬ i*"Q`ľmΛ|XVi-SS~"ca"0dLfzc5S.w{c2S^LBp?8y]D6@/3Lv@\Ɓ@<GgQ cgȨ 02M^Fc# ,42ܕ@aa2FȒ`I!$nsFF',R.CF'?d&j W.i! '&$!gôüHއMxNy&ڍv|"Ul6އџk=mV~`g=_q:bx8o,GVU63jm@v]v-q/卶Տő6kPLpRTx*26)PlpX܊"d>6ފD '[کX׭h=P[f#ʭ8e+fUCQÎP-AΒd˲yDilzϋ硍{}YiZ N Apkxo_%j|X}<Ғ6id)%h6t01фS¼V/$i`ʳ!K7OdfWE-m$W_M5rЪDliK[ʖ5ߔ mM#hSnS6&ҧ,3Æ^Jy4m$Oic?,#sYdy,-QƔ4Iۮw/{/)U\.bS@_Z>N2Lf|Fབo4wi=mL|:d|0 < N^u'O2&+Yv$?H.{ m6GV֙ <D[g~(%Uɔ&G8o3~5ne\:xSZ9TG~hBlQ*DF:1/:)pE Χm:т8ޘ(xM꼞G܍_7QH||B^֭ *+I ~)m>ML/c7|P>`m+ڬϸ0s7Y|(KڬߓOy0?Vt s`n6q:cY/hwDжYWQ$]6Ӫf]zj9eFCzN[u{zvL[/|ol[0>m!їaSz"1v3Ϩ[ocb5s̿v=~b=ؽ~/Hz!zً^\zm] Sc;2zƧS/f[z~y$6~y LcDNmz|nw nKS$Hn!_,>,mͺv)K>&ؔMatK7sm Cڰ9%q P&ΊӧF5+_6{>r$3NlǬڡ4O3gz;hԢ WCsF?]>[Zޒp,I󠏚lm6C ^5_}C:Niprz-&y/+^^9u G9ᔖ턎 Y2k^)粕;_Sg:Snf]Km2{rpUq5Ł7INaeWk൘aLoėZAF9.V#u:Ӷ|a|2l/밑O;}ǿh _nrTuRu2Vj]hq/lC\'y8l$wr Ґ >t2(o&?U7]I~zr{=4ǽ_ڐ{dŋvO.,e6rA{ /ٮLU5.U77_-b=63\9AOi.Gi{zs0둭wף|wu^^_ GYovcƃzjkƫ/ۡYrǡ'kSO'٩Gg3S3ꧩw_ք|v~%{H[Oԭ/OSlFʇ#qP?NSHM軨IJbQo,J>%z[zwD/^6':tS_,=^S;z~|-h}VT_Os[+l8Zb(nYg̰y[>*-ki'X=!ߔ=I}{fs̎S "O_J~?1endstream endobj 123 0 obj << /Type /Page /Parent 3 0 R /Contents 124 0 R /Resources 4 0 R >> endobj 124 0 obj << /Length 4169 /Filter /FlateDecode >> stream xZˮ]Cd5%PR&؈~֪ꗍ`[w?jժUuN>+;UV4]%59]]^/\>y;p?|w/G>ÿ7\{ ;XPד]w[澞jK\ׇKIw0~qo޼|oy<+&gxrX/zjΛ=\~Â#\*zw_͇#a%]Is}ɯ'z\ sdžsUD*ُ߿} />+g<߿g2Ap߬ i*"Q`ľmΛ|XVi-SS~"ca"0dLfzc5S.w{c2S^LBp?8y]D6@/3Lv@\Ɓ@<GgQ cgȨ 02M^Fc# ,42ܕ@aa2FȒ`I!$nsFF',R.CF'?d&j W.i! '&$!gôüHއMxNy&ڍv|"Ul6އџk=mV~`g=_q:bx8o,GVU63jm@v]v-q/卶Տő6kPLpRTx*26)PlpX܊"d>6ފD '[کX׭h=P[f#ʭ8e+fUCQÎP-AΒd˲yDilzϋ硍{}YiZ N Apkxo_%j|X}<Ғ6id)%h6t01фS¼V/$i`ʳ!K7OdfWE-m$W_M5rЪDliK[ʖ5ߔ mM#hSnS6&ҧ,3Æ^Jy4m$Oic?,#sYdy,-QƔ4Iۮw/{/)U\.bS@_Z>N2Lf|Fབo4wi=mL|:d|0 < N^u'O2&+Yv$?H.{ m6GV֙ <D[g~(%Uɔ&G8o3~5ne\:xSZ9TG~hBlQ*DF:1/:)pE Χm:т8ޘ(xM꼞G܍_7QH||B^֭ *+I ~)m>ML/c7|P>`m+ڬϸ0s7Y|(KڬߓOy0?Vt s`n6q:cY/hwDжYWQ$]6Ӫf]zj9eFCzN[u{zvL[/|ol[0>m!їaSz"1v3Ϩ[ocb5s̿v=~b=ؽ~/Hz!zً^\zm] Sc;2zƧS/f[z~y$6~y LcDNmz|nw nKS$Hn!_,>,mͺv)K>&ؔMatK7sm Cڰ9%q P&ΊӧF5+_6{>r$3NlǬڡ4O3gz;hԢ WCsF?]>[Zޒp,I󠏚lm6C ^5_}C:Niprz-&y/+^^9u G9ᔖ턎 Y2k^)粕;_Sg:Snf]Km2{rpUq5Ł7INaeWk൘aLoėZAF9.V#u:Ӷ|a|2l/밑O;}ǿh _nrTuRu2Vj]hq/lC\'y8l$wr Ґ >t2(o&?U7]I~zr{=4ǽ_ڐ{dŋvO.,e6rA{ /ٮLU5.U77_-b=63\9AOi.Gi{zs0둭wף|wu^^_ GYovcƃzjkƫ/ۡYrǡ'kSO'٩Gg3S3ꧩw_ք|v~%{H[Oԭ/OSlFʇ#qP?NSHM軨IJbQo,J>%z[zwD/^6':tS_,=^S;z~|-h}VT_Os[+l8Zb(nYg̰y[>*-ki'X=!ߔ=I}{fs̎S "O_J~?1endstream endobj 125 0 obj << /Type /Page /Parent 3 0 R /Contents 126 0 R /Resources 4 0 R >> endobj 126 0 obj << /Length 4169 /Filter /FlateDecode >> stream xZˮ]Cd5%PR&؈~֪ꗍ`[w?jժUuN>+;UV4]%59]]^/\>y;p?|w/G>ÿ7\{ ;XPד]w[澞jK\ׇKIw0~qo޼|oy<+&gxrX/zjΛ=\~Â#\*zw_͇#a%]Is}ɯ'z\ sdžsUD*ُ߿} />+g<߿g2Ap߬ i*"Q`ľmΛ|XVi-SS~"ca"0dLfzc5S.w{c2S^LBp?8y]D6@/3Lv@\Ɓ@<GgQ cgȨ 02M^Fc# ,42ܕ@aa2FȒ`I!$nsFF',R.CF'?d&j W.i! '&$!gôüHއMxNy&ڍv|"Ul6އџk=mV~`g=_q:bx8o,GVU63jm@v]v-q/卶Տő6kPLpRTx*26)PlpX܊"d>6ފD '[کX׭h=P[f#ʭ8e+fUCQÎP-AΒd˲yDilzϋ硍{}YiZ N Apkxo_%j|X}<Ғ6id)%h6t01фS¼V/$i`ʳ!K7OdfWE-m$W_M5rЪDliK[ʖ5ߔ mM#hSnS6&ҧ,3Æ^Jy4m$Oic?,#sYdy,-QƔ4Iۮw/{/)U\.bS@_Z>N2Lf|Fབo4wi=mL|:d|0 < N^u'O2&+Yv$?H.{ m6GV֙ <D[g~(%Uɔ&G8o3~5ne\:xSZ9TG~hBlQ*DF:1/:)pE Χm:т8ޘ(xM꼞G܍_7QH||B^֭ *+I ~)m>ML/c7|P>`m+ڬϸ0s7Y|(KڬߓOy0?Vt s`n6q:cY/hwDжYWQ$]6Ӫf]zj9eFCzN[u{zvL[/|ol[0>m!їaSz"1v3Ϩ[ocb5s̿v=~b=ؽ~/Hz!zً^\zm] Sc;2zƧS/f[z~y$6~y LcDNmz|nw nKS$Hn!_,>,mͺv)K>&ؔMatK7sm Cڰ9%q P&ΊӧF5+_6{>r$3NlǬڡ4O3gz;hԢ WCsF?]>[Zޒp,I󠏚lm6C ^5_}C:Niprz-&y/+^^9u G9ᔖ턎 Y2k^)粕;_Sg:Snf]Km2{rpUq5Ł7INaeWk൘aLoėZAF9.V#u:Ӷ|a|2l/밑O;}ǿh _nrTuRu2Vj]hq/lC\'y8l$wr Ґ >t2(o&?U7]I~zr{=4ǽ_ڐ{dŋvO.,e6rA{ /ٮLU5.U77_-b=63\9AOi.Gi{zs0둭wף|wu^^_ GYovcƃzjkƫ/ۡYrǡ'kSO'٩Gg3S3ꧩw_ք|v~%{H[Oԭ/OSlFʇ#qP?NSHM軨IJbQo,J>%z[zwD/^6':tS_,=^S;z~|-h}VT_Os[+l8Zb(nYg̰y[>*-ki'X=!ߔ=I}{fs̎S "O_J~?1endstream endobj 127 0 obj << /Type /Page /Parent 3 0 R /Contents 128 0 R /Resources 4 0 R >> endobj 128 0 obj << /Length 4169 /Filter /FlateDecode >> stream xZˮ]Cd5%PR&؈~֪ꗍ`[w?jժUuN>+;UV4]%59]]^/\>y;p?|w/G>ÿ7\{ ;XPד]w[澞jK\ׇKIw0~qo޼|oy<+&gxrX/zjΛ=\~Â#\*zw_͇#a%]Is}ɯ'z\ sdžsUD*ُ߿} />+g<߿g2Ap߬ i*"Q`ľmΛ|XVi-SS~"ca"0dLfzc5S.w{c2S^LBp?8y]D6@/3Lv@\Ɓ@<GgQ cgȨ 02M^Fc# ,42ܕ@aa2FȒ`I!$nsFF',R.CF'?d&j W.i! '&$!gôüHއMxNy&ڍv|"Ul6އџk=mV~`g=_q:bx8o,GVU63jm@v]v-q/卶Տő6kPLpRTx*26)PlpX܊"d>6ފD '[کX׭h=P[f#ʭ8e+fUCQÎP-AΒd˲yDilzϋ硍{}YiZ N Apkxo_%j|X}<Ғ6id)%h6t01фS¼V/$i`ʳ!K7OdfWE-m$W_M5rЪDliK[ʖ5ߔ mM#hSnS6&ҧ,3Æ^Jy4m$Oic?,#sYdy,-QƔ4Iۮw/{/)U\.bS@_Z>N2Lf|Fབo4wi=mL|:d|0 < N^u'O2&+Yv$?H.{ m6GV֙ <D[g~(%Uɔ&G8o3~5ne\:xSZ9TG~hBlQ*DF:1/:)pE Χm:т8ޘ(xM꼞G܍_7QH||B^֭ *+I ~)m>ML/c7|P>`m+ڬϸ0s7Y|(KڬߓOy0?Vt s`n6q:cY/hwDжYWQ$]6Ӫf]zj9eFCzN[u{zvL[/|ol[0>m!їaSz"1v3Ϩ[ocb5s̿v=~b=ؽ~/Hz!zً^\zm] Sc;2zƧS/f[z~y$6~y LcDNmz|nw nKS$Hn!_,>,mͺv)K>&ؔMatK7sm Cڰ9%q P&ΊӧF5+_6{>r$3NlǬڡ4O3gz;hԢ WCsF?]>[Zޒp,I󠏚lm6C ^5_}C:Niprz-&y/+^^9u G9ᔖ턎 Y2k^)粕;_Sg:Snf]Km2{rpUq5Ł7INaeWk൘aLoėZAF9.V#u:Ӷ|a|2l/밑O;}ǿh _nrTuRu2Vj]hq/lC\'y8l$wr Ґ >t2(o&?U7]I~zr{=4ǽ_ڐ{dŋvO.,e6rA{ /ٮLU5.U77_-b=63\9AOi.Gi{zs0둭wף|wu^^_ GYovcƃzjkƫ/ۡYrǡ'kSO'٩Gg3S3ꧩw_ք|v~%{H[Oԭ/OSlFʇ#qP?NSHM軨IJbQo,J>%z[zwD/^6':tS_,=^S;z~|-h}VT_Os[+l8Zb(nYg̰y[>*-ki'X=!ߔ=I}{fs̎S "O_J~?1endstream endobj 129 0 obj << /Type /Page /Parent 3 0 R /Contents 130 0 R /Resources 4 0 R >> endobj 130 0 obj << /Length 4169 /Filter /FlateDecode >> stream xZˮ]Cd5%PR&؈~֪ꗍ`[w?jժUuN>+;UV4]%59]]^/\>y;p?|w/G>ÿ7\{ ;XPד]w[澞jK\ׇKIw0~qo޼|oy<+&gxrX/zjΛ=\~Â#\*zw_͇#a%]Is}ɯ'z\ sdžsUD*ُ߿} />+g<߿g2Ap߬ i*"Q`ľmΛ|XVi-SS~"ca"0dLfzc5S.w{c2S^LBp?8y]D6@/3Lv@\Ɓ@<GgQ cgȨ 02M^Fc# ,42ܕ@aa2FȒ`I!$nsFF',R.CF'?d&j W.i! '&$!gôüHއMxNy&ڍv|"Ul6އџk=mV~`g=_q:bx8o,GVU63jm@v]v-q/卶Տő6kPLpRTx*26)PlpX܊"d>6ފD '[کX׭h=P[f#ʭ8e+fUCQÎP-AΒd˲yDilzϋ硍{}YiZ N Apkxo_%j|X}<Ғ6id)%h6t01фS¼V/$i`ʳ!K7OdfWE-m$W_M5rЪDliK[ʖ5ߔ mM#hSnS6&ҧ,3Æ^Jy4m$Oic?,#sYdy,-QƔ4Iۮw/{/)U\.bS@_Z>N2Lf|Fབo4wi=mL|:d|0 < N^u'O2&+Yv$?H.{ m6GV֙ <D[g~(%Uɔ&G8o3~5ne\:xSZ9TG~hBlQ*DF:1/:)pE Χm:т8ޘ(xM꼞G܍_7QH||B^֭ *+I ~)m>ML/c7|P>`m+ڬϸ0s7Y|(KڬߓOy0?Vt s`n6q:cY/hwDжYWQ$]6Ӫf]zj9eFCzN[u{zvL[/|ol[0>m!їaSz"1v3Ϩ[ocb5s̿v=~b=ؽ~/Hz!zً^\zm] Sc;2zƧS/f[z~y$6~y LcDNmz|nw nKS$Hn!_,>,mͺv)K>&ؔMatK7sm Cڰ9%q P&ΊӧF5+_6{>r$3NlǬڡ4O3gz;hԢ WCsF?]>[Zޒp,I󠏚lm6C ^5_}C:Niprz-&y/+^^9u G9ᔖ턎 Y2k^)粕;_Sg:Snf]Km2{rpUq5Ł7INaeWk൘aLoėZAF9.V#u:Ӷ|a|2l/밑O;}ǿh _nrTuRu2Vj]hq/lC\'y8l$wr Ґ >t2(o&?U7]I~zr{=4ǽ_ڐ{dŋvO.,e6rA{ /ٮLU5.U77_-b=63\9AOi.Gi{zs0둭wף|wu^^_ GYovcƃzjkƫ/ۡYrǡ'kSO'٩Gg3S3ꧩw_ք|v~%{H[Oԭ/OSlFʇ#qP?NSHM軨IJbQo,J>%z[zwD/^6':tS_,=^S;z~|-h}VT_Os[+l8Zb(nYg̰y[>*-ki'X=!ߔ=I}{fs̎S "O_J~?1endstream endobj 131 0 obj << /Type /Page /Parent 3 0 R /Contents 132 0 R /Resources 4 0 R >> endobj 132 0 obj << /Length 3963 /Filter /FlateDecode >> stream xZ.qO1d3"8aHt,,bGI  d n$K@{ĹjΗ7|a ?/hfqOߌcџ_,t,5ւ f)oHoNMypZ,.QUuގ' SrJp&`㹿E1ր-mq\rj\q9wĸu<aX߁s~{8cI1.`~ܞϯ1絷zxz q,x{;懠oBx1=LN3^qy+oq/20̟?xʨ7av he >Z<8%@3bȖxx Q q3%Oʛ>l-lr@5m$_.;0"!x}й3 /uso\/x/^k&}9a4VDj?Z]ċ;c+= 6d${nvra+%6lH[fd+TQ<$B$wnt0Kny Wdc߅D T1pP)`t*;w42T Ϙ]$M7t`<7_Jc qi7.rz!7/W_`uS5WoPv#$ qF b>|H1_@X#^[O``J~Bljyy\?.DʥoI-' :]:@K(S{?E3k1׿J q*)PĚOUވ~*܏U;J+ xxqn3xSW~hqpv$謗c]M3OK^Y#"?rLxvTuWm#1o۱Q/Qcr 'u)oZnG bq-.|hзA46ԀXǶP7LkqVxRo#_< C":ߣt(:sm [)}_/+/?}|ky>}xa»1O>O`QF{} l NJbkpv ^鈿Q$6m:T&#DVf\ĜW[H(,QL@=(2ȵ RMEz|&vP^LI^$-(@{< EӀV &$& 5  qe7,󅚔 M$;ƱHНd"qSPҝT9@,#Dn&ݡ|9L>cj8@G$ y & a>Mɧj/ڢHw?&0qHl{){ MzUHp"R$@`=ȇ&D&ƅ|>/Li7 L>0~ȇT#$->!>1_w||"Y|$' >a#t!Q-zLSTW o@l@MxAɃOM |R7 NQ5OE\'J0 :1QQO iD'`EQM}OЏLݬ&Fy`T>_$LM>Q2֧Ɖ+m,}D`|~z':_>ڢ ^'1-}kP+O aL\ߜ?y N 5_gZkn]rv<ߊW[I+ uGs~\|q`ozgS7_0@'X(/X'خ||m|勩?+e􀘇K/|hlQK6K/=S.;PS4K/?KO1|[޴n=&f^scYkvbo'Q!ɪCO=Q֯s|#zEܮz<&zH\>>N%CYPfk9٩?g,/p|zM~gWpw!IC7?E~f;~.фm ؁F r"\o?^~H?*MݎDn?Dzik6&J80בk,?=~MZ=~Muȉ٤ԧ0݁-A;+i1a߼Hym}<]XbGNWg(~>#Y<3#f9Ŷ)1ERb`,yF~T?߯nFS{3h__\1˟;V(gq6Ī}ƫ=_Fe*N܏vw_?(^]R鴿QSqE~о<#'>8%e$zQ2OEy p=pg9k;~<60Q렶'EmZĴ*,p5~d@Yi CH([aw"u/-?ԋ懊 =х  K%ĉ]liڿLu g.\qo= .=< 4IEwiZr^1HG{F&'Ћ/ {I "x!l7~k4&^=M/>XJbe.dɲ'q뇏Df,20( lwߍ䃉|aO&3wǨ(u嫉 go'߹?}Eendstream endobj 133 0 obj << /Type /Page /Parent 3 0 R /Contents 134 0 R /Resources 4 0 R >> endobj 134 0 obj << /Length 3953 /Filter /FlateDecode >> stream xZˮ%Gܟ%l]Y-d̕X 5Y/dsGUeEFF9JW׷_^ߏ]Uo˒U.r}?w~:wk׿_\}3x9// ~B3{lޮ_|RV1$.Nա-_]{8[4uNؕq[x.=?~\SI ׻+a!EƊRF\8Z̕/Vy;43p"Ncx`~Xdŧt[1x=VO+c|N51nb m)'}|vDK"rof a~`^e "\#|fg= w%<3{ŹwS*i >pgr?+b !n=>/0 KEwRɷʛ1N,m90D65grr2 ⏼ju@ޜrεrSr1!aH} |j8:"8mx3ި-fA1x&nt,B5Ngl )|2$`ƎVc `, 0 ' 0i2qm0 ]`<&HFF`ı1ޏċw.ԔȰFܘw(A32J/#1 p $왊1>2(\/2R8+d(&"* [3^-c(F\Cy/cK̏|?2v(b 2bJډ [`^9pcra>סIwϒGm"n%R#~`cc K$pߠ# =oDXʇ7|h2_W>z|3!Վ|-^Aw>CWɏ{.=)z^T[O 9zSkQ-|֫zQ~K SKXR󡥩)׷ : } uj+qXO>13j1ֿJ q9*_]5Q8?:YYgz(\(*/ 3Ϻͅ:v_4_i{"};FNG~$= ; F3ʺcBX&Xu;6VOGW^nLJ@2OF0qb#'ۑBXhc.c@혡WG ḱZ!b:ˮS-6Tsm7bi { []EUI>ԪIbz`T3 bFWΟMo>^\oz҄8y}o߽~և+A醱P_^$4edvsn`#M̆8zJeCLRf\tǍ|<渲,,Ydm#q ,7r%KYi[xZeeXz{ 'NYlɈ'1˚Ef=.QǴi8eUhX1^#xEO>?\C,>`Y~)l=Za6mELbmMOl[/I2ML)ṁ6edΗ67 d6ԐIbޣ1|jfئT F\x=:&?~-@uIؐ4 3kN%m+e!}%/no ᴸՈ'on, "OAzx#e*!baVm6yKu/ʰՑ(h/oMi= 6Jj D\Fզ> N1+0FSo>n3V&DmW|~->!1y0uS'_{O>ww|[ґ/':ŝoۀW1|0@8V+%z@LL/8SozYKY?q`;N PS/Yraꭦh[kK֯ʃպm ,If &?W!F]Q4]iCbY/QOz̨Pzs NM?xLWHgRq~'9ݜl-;~8~<~j=$'z#ޔÏ6/6?v~L,ovq`˯7﷟GbO/̶q5W9ȉ٦x;Tg2˟wŁH[-3l֝5NQ^a) ysfDv?GCOAA<jæ=`<+NH85"c))3=S;/G :])Bv̻x޼Y~>;'o\)b(C{NqWj_=o)gdyG?u6!l5[_C9RzyGAvSEW>G9)- -*◣dֺe/w1>OY.K3(r 0zWs_*eU 9@kv`ogs;L,aӾB`ǟono~J;n>>g|S!m> {3;ڹ^?Rv'D3lu%4b?a߹_~YhJ__Ox[ އ*N\vUCgfiv2+5Z_QN0AoZAF9.^#tm!_ly n#4>w$V}'h_7G95:0oty;6ž2V/ H\hKi/0\~y40Իx !~&2mcsdRp>i 9ƕ±'F_mDžc5K @p^]byxCW )k?,_~r`-{}",'Bveɒ1ȅ2&_-y N3P8rO&Vq#GMʍc|6|7㋩'[/H ӭ'_]1/=2W+=3u",3vqꡙfΗfߥEl^sOe=q>q9_]O Y|gqg_u%ՎzjnG=~Oz*9ЬLt= ۵'ovv+;E0 i5a+~Su- cԧۯQ(RHMh臦²BY~?%~{~ݶ/_~Ntl=>X~jۯ[G?P~~RR1@Sw ?Ov+Gv[v߀+ ?4ݏ>'.ď> endobj 4 0 obj << /ProcSet [/PDF /Text] /Font << /F1 136 0 R /F2 137 0 R /F3 138 0 R >> /ExtGState << >> /ColorSpace << /sRGB 5 0 R >> >> endobj 5 0 obj [/ICCBased 6 0 R] endobj 6 0 obj << /Alternate /DeviceRGB /N 3 /Length 2596 /Filter /FlateDecode >> stream xwTSϽ7PkhRH H.*1 J"6DTpDQ2(C"QDqpId߼y͛~kg}ֺLX Xňg` lpBF|،l *?Y"1P\8=W%Oɘ4M0J"Y2Vs,[|e92<se'9`2&ctI@o|N6(.sSdl-c(2-yH_/XZ.$&\SM07#1ؙYrfYym";8980m-m(]v^DW~ emi]P`/u}q|^R,g+\Kk)/C_|Rax8t1C^7nfzDp 柇u$/ED˦L L[B@ٹЖX!@~(* {d+} G͋љς}WL$cGD2QZ4 E@@A(q`1D `'u46ptc48.`R0) @Rt CXCP%CBH@Rf[(t CQhz#0 Zl`O828.p|O×X ?:0FBx$ !i@ڐH[EE1PL ⢖V6QP>U(j MFkt,:.FW8c1L&ӎ9ƌaX: rbl1 {{{;}#tp8_\8"Ey.,X%%Gщ1-9ҀKl.oo/O$&'=JvMޞxǥ{=Vs\x ‰N柜>ucKz=s/ol|ϝ?y ^d]ps~:;/;]7|WpQoH!ɻVsnYs}ҽ~4] =>=:`;cܱ'?e~!ańD#G&}'/?^xI֓?+\wx20;5\ӯ_etWf^Qs-mw3+?~O~endstream endobj 135 0 obj << /Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [ 45/minus 96/quoteleft 144/dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron /space] >> endobj 136 0 obj << /Type /Font /Subtype /Type1 /Name /F1 /BaseFont /ZapfDingbats >> endobj 137 0 obj << /Type /Font /Subtype /Type1 /Name /F2 /BaseFont /Helvetica /Encoding 135 0 R >> endobj 138 0 obj << /Type /Font /Subtype /Type1 /Name /F3 /BaseFont /Helvetica-Bold /Encoding 135 0 R >> endobj xref 0 139 0000000000 65535 f 0000000021 00000 n 0000000163 00000 n 0000236356 00000 n 0000236897 00000 n 0000237035 00000 n 0000237068 00000 n 0000000212 00000 n 0000000292 00000 n 0000001075 00000 n 0000001156 00000 n 0000005429 00000 n 0000005511 00000 n 0000009740 00000 n 0000009822 00000 n 0000014153 00000 n 0000014235 00000 n 0000018565 00000 n 0000018647 00000 n 0000023001 00000 n 0000023083 00000 n 0000023908 00000 n 0000023990 00000 n 0000028302 00000 n 0000028384 00000 n 0000032697 00000 n 0000032779 00000 n 0000037095 00000 n 0000037177 00000 n 0000041616 00000 n 0000041698 00000 n 0000046033 00000 n 0000046115 00000 n 0000050454 00000 n 0000050536 00000 n 0000054853 00000 n 0000054935 00000 n 0000059291 00000 n 0000059373 00000 n 0000063736 00000 n 0000063818 00000 n 0000064643 00000 n 0000064725 00000 n 0000069038 00000 n 0000069120 00000 n 0000069969 00000 n 0000070051 00000 n 0000074395 00000 n 0000074477 00000 n 0000075311 00000 n 0000075393 00000 n 0000079716 00000 n 0000079798 00000 n 0000084125 00000 n 0000084207 00000 n 0000088555 00000 n 0000088637 00000 n 0000089462 00000 n 0000089544 00000 n 0000093253 00000 n 0000093335 00000 n 0000096867 00000 n 0000096949 00000 n 0000101237 00000 n 0000101319 00000 n 0000104993 00000 n 0000105075 00000 n 0000108571 00000 n 0000108653 00000 n 0000112856 00000 n 0000112938 00000 n 0000116554 00000 n 0000116636 00000 n 0000120061 00000 n 0000120143 00000 n 0000120968 00000 n 0000121050 00000 n 0000125363 00000 n 0000125445 00000 n 0000126294 00000 n 0000126376 00000 n 0000130720 00000 n 0000130802 00000 n 0000131636 00000 n 0000131718 00000 n 0000136041 00000 n 0000136123 00000 n 0000140450 00000 n 0000140532 00000 n 0000144880 00000 n 0000144962 00000 n 0000149193 00000 n 0000149275 00000 n 0000153582 00000 n 0000153664 00000 n 0000157948 00000 n 0000158030 00000 n 0000158855 00000 n 0000158937 00000 n 0000162646 00000 n 0000162729 00000 n 0000166262 00000 n 0000166346 00000 n 0000170624 00000 n 0000170708 00000 n 0000175100 00000 n 0000175184 00000 n 0000179556 00000 n 0000179640 00000 n 0000180425 00000 n 0000180509 00000 n 0000184783 00000 n 0000184867 00000 n 0000189110 00000 n 0000189194 00000 n 0000193508 00000 n 0000193592 00000 n 0000197835 00000 n 0000197919 00000 n 0000202162 00000 n 0000202246 00000 n 0000206489 00000 n 0000206573 00000 n 0000210816 00000 n 0000210900 00000 n 0000215143 00000 n 0000215227 00000 n 0000219470 00000 n 0000219554 00000 n 0000223797 00000 n 0000223881 00000 n 0000228124 00000 n 0000228208 00000 n 0000232245 00000 n 0000232329 00000 n 0000239763 00000 n 0000240022 00000 n 0000240107 00000 n 0000240207 00000 n trailer << /Size 139 /Info 1 0 R /Root 2 0 R >> startxref 240312 %%EOF vioplot/tests/testthat/test_violin_na_handle.R0000755000176200001440000000236313411056063021431 0ustar liggesuserslibrary("vioplot") context("NA handling for vector or formula input") test_that("plot data list input", { data(iris) iris[2,3]<-NA boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length") }) test_that("plot vector formula input", { boxplot(iris$Sepal.Length~iris$Species) vioplot(iris$Sepal.Length~iris$Species) }) test_that("plot column formula with dataframe input", { boxplot(Sepal.Length~Species, data=iris) vioplot(Sepal.Length~Species, data=iris) }) test_that("plot formula with dataframe input and scalar colour", { vioplot(Sepal.Length~Species, data=iris, col="lightblue") }) test_that("plot formula with dataframe input and vector colour", { vioplot(Sepal.Length~Species, data=iris, col=c("lightgreen", "lightblue", "palevioletred")) }) # iris <- as.matrix(iris) # test_that("plot column formula with matrix input", { # vioplot(Sepal.Length~Species, data=iris) # }) vioplot/tests/testthat/test_violin_unequal_groups.R0000755000176200001440000000117413411056063022570 0ustar liggesuserslibrary("vioplot") context("unequal group size") data(iris) table(iris$Species) identical(as.numeric(table(iris$Species)), c(50, 50, 50)) index <- sample(1:3,150,replace=T) while(identical(as.numeric(table(index)), c(50, 50, 50))) index <- sample(1:3,150,replace=T) table(index) iris$Species <- factor(names(table(iris$Species))[index]) test_that("list input", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"]) }) test_that("formulae input", { vioplot(iris$Sepal.Length~iris$Species) vioplot(Sepal.Length~Species, data=iris) }) vioplot/tests/testthat/test_violin_area.R0000755000176200001440000000410513411056063020424 0ustar liggesuserslibrary("vioplot") context("controlling area") test_that("plot defaults", { data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) }) ##Violin Plot Area test_that("equal area with areaEqual TRUE", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", areaEqual = TRUE) }) test_that("equal width with areaEqual FALSE", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Width)", areaEqual = FALSE) }) test_that("equal area with areaEqual with vector colours", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = TRUE, col=c("lightgreen", "lightblue", "palevioletred"), rectCol=c("green", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), border=c("darkolivegreen4", "royalblue4", "violetred4")) }) test_that("equal area with areaEqual and wex scaling", { vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = TRUE, col=c("lightgreen", "lightblue", "palevioletred"), rectCol=c("green", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), border=c("darkolivegreen4", "royalblue4", "violetred4"), wex=1.25) }) vioplot/tests/testthat.R0000755000176200001440000000007213411056063015074 0ustar liggesuserslibrary(testthat) library(vioplot) test_check("vioplot") vioplot/vignettes/0000755000176200001440000000000013570230421013753 5ustar liggesusersvioplot/vignettes/violin_split.Rmd0000755000176200001440000001374613507766533017172 0ustar liggesusers--- title: "Split Violin Plots" author: "Tom Kelly" date: "`r Sys.Date()`" output: rmarkdown::html_vignette fig_width: 6 fig_height: 3 fig_align: 'center' fig_keep: 'last' vignette: > %\VignetteIndexEntry{vioplot: Split Violin Plots} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ##Violin Plots Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits: - Greater flexibility for plotting variation than boxplots - More familiarity to boxplot users than density plots - Easier to directly compare data types than existing plots As shown below for the `iris` dataset, violin plots show distribution information that the boxplot is unable to. ###General Set up ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} library("vioplot") ``` We set up the data with two categories (Sepal Width) as follows: ```{r, message=FALSE} data(iris) summary(iris$Sepal.Width) table(iris$Sepal.Width > mean(iris$Sepal.Width)) iris_large <- iris[iris$Sepal.Width > mean(iris$Sepal.Width), ] iris_small <- iris[iris$Sepal.Width <= mean(iris$Sepal.Width), ] ``` ###Boxplots First we plot Sepal Length on its own: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} boxplot(Sepal.Length~Species, data=iris, col="grey") ``` An indirect comparison can be achieved with par: ```{r, fig.align = 'center', fig.height = 6, fig.width = 6, fig.keep = 'last'} { par(mfrow=c(2,1)) boxplot(Sepal.Length~Species, data=iris_small, col = "lightblue") boxplot(Sepal.Length~Species, data=iris_large, col = "palevioletred") par(mfrow=c(1,1)) } ``` ### Violin Plots First we plot Sepal Length on its own: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} vioplot(Sepal.Length~Species, data=iris) ``` An indirect comparison can be achieved with par: ```{r, fig.align = 'center', fig.height = 6, fig.width = 6, fig.keep = 'last'} { par(mfrow=c(2,1)) vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "line") vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "line") par(mfrow=c(1,1)) } ``` ### Split Violin Plots A more direct comparision can be made with the `side` argument and `add = TRUE` on the second plot: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "line", side = "right") vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "line", side = "left", add = T) title(xlab = "Species", ylab = "Sepal Length") legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width") ``` ### median The line median option is more suitable for side by side comparisions but the point option is still available also: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "point", side = "right", pchMed = 21, colMed = "palevioletred4", colMed2 = "palevioletred2") vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "point", side = "left", pchMed = 21, colMed = "lightblue4", colMed2 = "lightblue2", add = T) title(xlab = "Species", ylab = "Sepal Length") legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width") ``` It may be necessary to include a `points` command to fix the median being overwritten by the following plots: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "point", side = "right", pchMed = 21, colMed = "palevioletred4", colMed2 = "palevioletred2") vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "point", side = "left", pchMed = 21, colMed = "lightblue4", colMed2 = "lightblue2", add = T) points(1:length(levels(iris$Species)), as.numeric(sapply(levels(iris$Species), function(species) median(iris_large[grep(species, iris_large$Species),]$Sepal.Length))), pch = 21, col = "palevioletred4", bg = "palevioletred2") title(xlab = "Species", ylab = "Sepal Length") legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width") ``` Similarly points could be added where a line has been used previously: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "line", side = "right", pchMed = 21, colMed = "palevioletred4", colMed2 = "palevioletred2") vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "line", side = "left", pchMed = 21, colMed = "lightblue4", colMed2 = "lightblue2", add = T) points(1:length(levels(iris$Species)), as.numeric(sapply(levels(iris$Species), function(species) median(iris_large[grep(species, iris_large$Species),]$Sepal.Length))), pch = 21, col = "palevioletred4", bg = "palevioletred2") points(1:length(levels(iris$Species)), as.numeric(sapply(levels(iris$Species), function(species) median(iris_small[grep(species, iris_small$Species),]$Sepal.Length))), pch = 21, col = "lightblue4", bg = "lightblue2") title(xlab = "Species", ylab = "Sepal Length") legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width") ``` Here it is aesthetically pleasing and intuitive to interpret categorical differences in mean and variation in a continuous variable. #### Sources These extensions to `vioplot` here are based on those provided here: * https://gist.github.com/mbjoseph/5852613 These have previously been discussed on the following sites: * https://mbjoseph.github.io/posts/2018-12-23-split-violin-plots/ * http://tagteam.harvard.edu/hub_feeds/1981/feed_items/209875 * https://www.r-bloggers.com/split-violin-plots/ vioplot/vignettes/backup/0000755000176200001440000000000013507674421015234 5ustar liggesusersvioplot/vignettes/backup/violin_split.Rmd0000644000176200001440000001374313507652103020414 0ustar liggesusers--- title: "Split Violin Plots" author: "Tom Kelly" date: "`r Sys.Date()`" output: rmarkdown::html_vignette fig_width: 6 fig_height: 3 fig_align: 'center' fig_keep: 'last' vignette: > %\VignetteIndexEntry{vioplot: Split Violin Plots} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ##Violin Plots Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits: - Greater flexbility for plotting variation than boxplots - More familiarity to boxplot users than density plots - Easier to directly compare data types than existing plots As shown below for the `iris` dataset, violin plots show distribution information that the boxplot is unable to. ###General Set up ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} library("vioplot") ``` We set up the data with two categories (Sepal Width) as follows: ```{r, message=FALSE} data(iris) summary(iris$Sepal.Width) table(iris$Sepal.Width > mean(iris$Sepal.Width)) iris_large <- iris[iris$Sepal.Width > mean(iris$Sepal.Width), ] iris_small <- iris[iris$Sepal.Width <= mean(iris$Sepal.Width), ] ``` ###Boxplots First we plot Sepal Length on its own: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} boxplot(Sepal.Length~Species, data=iris, col="grey") ``` An indirect comparison can be achieved with par: ```{r, fig.align = 'center', fig.height = 6, fig.width = 6, fig.keep = 'last'} { par(mfrow=c(2,1)) boxplot(Sepal.Length~Species, data=iris_small, col = "lightblue") boxplot(Sepal.Length~Species, data=iris_large, col = "palevioletred") par(mfrow=c(1,1)) } ``` ### Violin Plots First we plot Sepal Length on its own: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} vioplot(Sepal.Length~Species, data=iris) ``` An indirect comparison can be achieved with par: ```{r, fig.align = 'center', fig.height = 6, fig.width = 6, fig.keep = 'last'} { par(mfrow=c(2,1)) vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "line") vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "line") par(mfrow=c(1,1)) } ``` ### Split Violin Plots A more direct comparison can be made with the `side` argument and `add = TRUE` on the second plot: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "line", side = "right") vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "line", side = "left", add = T) title(xlab = "Species", ylab = "Sepal Length") legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width") ``` ### median The line median option is more suitable for side by side comparisons but the point option is still available also: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "point", side = "right", pchMed = 21, colMed = "palevioletred4", colMed2 = "palevioletred2") vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "point", side = "left", pchMed = 21, colMed = "lightblue4", colMed2 = "lightblue2", add = T) title(xlab = "Species", ylab = "Sepal Length") legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width") ``` It may be necessary to include a `points` command to fix the median being overwritten by the following plots: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "point", side = "right", pchMed = 21, colMed = "palevioletred4", colMed2 = "palevioletred2") vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "point", side = "left", pchMed = 21, colMed = "lightblue4", colMed2 = "lightblue2", add = T) points(1:length(levels(iris$Species)), as.numeric(sapply(levels(iris$Species), function(species) median(iris_large[grep(species, iris_large$Species),]$Sepal.Length))), pch = 21, col = "palevioletred4", bg = "palevioletred2") title(xlab = "Species", ylab = "Sepal Length") legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width") ``` Similarly points could be added where a line has been used previously: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "line", side = "right", pchMed = 21, colMed = "palevioletred4", colMed2 = "palevioletred2") vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "line", side = "left", pchMed = 21, colMed = "lightblue4", colMed2 = "lightblue2", add = T) points(1:length(levels(iris$Species)), as.numeric(sapply(levels(iris$Species), function(species) median(iris_large[grep(species, iris_large$Species),]$Sepal.Length))), pch = 21, col = "palevioletred4", bg = "palevioletred2") points(1:length(levels(iris$Species)), as.numeric(sapply(levels(iris$Species), function(species) median(iris_small[grep(species, iris_small$Species),]$Sepal.Length))), pch = 21, col = "lightblue4", bg = "lightblue2") title(xlab = "Species", ylab = "Sepal Length") legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width") ``` Here it is aesthetically pleasing and intuitive to interpret categorical differences in mean and variation in a continuous variable. #### Sources These extensions to `vioplot` here are based on those provided here: * https://gist.github.com/mbjoseph/5852613 These have previously been discussed on the following sites: * https://mbjoseph.github.io/posts/2018-12-23-split-violin-plots/ * http://tagteam.harvard.edu/hub_feeds/1981/feed_items/209875 * https://www.r-bloggers.com/split-violin-plots/ vioplot/vignettes/backup/violin_ylog.Rmd0000644000176200001440000001121113507661566020234 0ustar liggesusers--- title: "Controlling y-axis Plotting" author: "Tom Kelly" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{vioplot: Controlling y-axis Plotting} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- While boxplots have become the _de facto_ standard for plotting the distribution of data this is a vast oversimplification and may not show everything needed to evaluate the variation of data. This is particularly important for datasets which do not form a Gaussian "Normal" distribution that most researchers have become accustomed to. While density plots are helpful in this regard, they can be less aesthetically pleasing than boxplots and harder to interpret for those familiar with boxplots. Often the only ways to compare multiple data types with density use slices of the data with faceting the plotting panes or overlaying density curves with colours and a legend. This approach is jarring for new users and leads to cluttered plots difficult to present to a wider audience. ##Violin Plots Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits: - Greater flexbility for plotting variation than boxplots - More familiarity to boxplot users than density plots - Easier to directly compare data types than existing plots As shown below for the `iris` dataset, violin plots show distribution information that the boxplot is unable to. ```{r} library("vioplot") ``` ```{r, message=FALSE} data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) ``` ##Violin y-axis ###Logarithmic scale However the existing violin plot packages (such as \code{\link[vioplot]{vioplot}}) do not support log-scale of the y-axis. This has been amended with the `ylog` argument. ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", ylog = T) ``` This can also be invoked with the `log="y"` argument compatible with `boxplot`: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = T) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = "y") ``` Log axis can also be passed to horizontal plots: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = "", horizontal = TRUE) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = "y", horizontal = TRUE) ``` ###custom y-axes The y-axes can also be removed with `yaxt="n"` to enable customised y-axes: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", yaxt="n") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", ylog = T, yaxt="n") ``` Thus custom axes can be added to violin plots. As shown on a linear scale: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", yaxt="n") axis(2, at=1:10, labels=1:10) ``` As well as for on a log scale: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", yaxt="n", log="y", ylim=c(log(4), log(9))) axis(2, at=log(1:10), labels=1:10) ``` vioplot/vignettes/backup/violin_split.html0000755000176200001440000462432313320630501020636 0ustar liggesusers Split Violin Plots

Violin Plots

Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits:

  • Greater flexbility for plotting variation than boxplots
  • More familiarity to boxplot users than density plots
  • Easier to directly compare data types than existing plots

As shown below for the iris dataset, violin plots show distribution information that the boxplot is unable to.

General Set up

We set up the data with two categories (Sepal Width) as follows:

data(iris)
summary(iris$Sepal.Width)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   2.000   2.800   3.000   3.057   3.300   4.400
table(iris$Sepal.Width > mean(iris$Sepal.Width))
## 
## FALSE  TRUE 
##    83    67
iris_large <- iris[iris$Sepal.Width > mean(iris$Sepal.Width), ]
iris_small <- iris[iris$Sepal.Width <= mean(iris$Sepal.Width), ]

Boxplots

First we plot Sepal Length on its own:

boxplot(Sepal.Length~Species, data=iris, col="grey")

An indirect comparision can be achieved with par:

par(mfrow=c(2,1))
boxplot(Sepal.Length~Species, data=iris_small, col = "lightblue")
boxplot(Sepal.Length~Species, data=iris_large, col = "palevioletred")

par(mfrow=c(1,1))

Violin Plots

First we plot Sepal Length on its own:

vioplot(Sepal.Length~Species, data=iris)

An indirect comparision can be achieved with par:

par(mfrow=c(2,1))
vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "line")
vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "line")

par(mfrow=c(1,1))

Split Violin Plots

A more direct comparision can be made with the side argument and add = TRUE on the second plot:

vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "line", side = "right")
vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "line", side = "left", add = T)
title(xlab = "Species", ylab = "Sepal Length")
legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width")

median

The line median option is more suitable for side by side comparisions but the point option is still available also:

vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "point", side = "right", pchMed = 21, colMed = "palevioletred4", colMed2 = "palevioletred2")
vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "point", side = "left", pchMed = 21, colMed = "lightblue4", colMed2 = "lightblue2", add = T)
title(xlab = "Species", ylab = "Sepal Length")
legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width")

It may be necessary to include a points command to fix the median being overwritten by the following plots:

vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "point", side = "right", pchMed = 21, colMed = "palevioletred4", colMed2 = "palevioletred2")
vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "point", side = "left", pchMed = 21, colMed = "lightblue4", colMed2 = "lightblue2", add = T)
points(1:length(levels(iris$Species)), as.numeric(sapply(levels(iris$Species), function(species) median(iris_large[grep(species, iris_large$Species),]$Sepal.Length))), pch = 21, col = "palevioletred4", bg = "palevioletred2")
title(xlab = "Species", ylab = "Sepal Length")
legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width")

Similarly points could be added where a line has been used previously:

vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "line", side = "right", pchMed = 21, colMed = "palevioletred4", colMed2 = "palevioletred2")
vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "line", side = "left", pchMed = 21, colMed = "lightblue4", colMed2 = "lightblue2", add = T)
points(1:length(levels(iris$Species)), as.numeric(sapply(levels(iris$Species), function(species) median(iris_large[grep(species, iris_large$Species),]$Sepal.Length))), pch = 21, col = "palevioletred4", bg = "palevioletred2")
points(1:length(levels(iris$Species)), as.numeric(sapply(levels(iris$Species), function(species) median(iris_small[grep(species, iris_small$Species),]$Sepal.Length))), pch = 21, col = "lightblue4", bg = "lightblue2")
title(xlab = "Species", ylab = "Sepal Length")
legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width")

Here it is aesthetically pleasing and intuitive to interpret categorical differences in mean and variation in a continuous variable.

vioplot/vignettes/backup/violin_area.html0000755000176200001440000537227213320630501020417 0ustar liggesusers Controlling Violin Plot Area

While boxplots have become the de facto standard for plotting the distribution of data this is a vast oversimplification and may not show everything needed to evaluate the variation of data. This is particularly important for datasets which do not form a Guassian “Normal” distribution that most researchers have become accustomed to.

While density plots are helpful in this regard, they can be less aesthetically pleasing than boxplots and harder to interpret for those familiar with boxplots. Often the only ways to compare multiple data types with density use slices of the data with faceting the plotting panes or overlaying density curves with colours and a legend. This approach is jarring for new users and leads to cluttered plots difficult to present to a wider audience.

Violin Plots

Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits:

  • Greater flexbility for plotting variation than boxplots
  • More familiarity to boxplot users than density plots
  • Easier to directly compare data types than existing plots

As shown below for the iris dataset, violin plots show distribution information that the boxplot is unable to.

data(iris)
boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"))

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"))

Violin Plot Area

However there are concerns that existing violin plot packages (such as ) scales the data to the most aesthetically suitable width rather than maintaining proportions comparable across data sets. Consider the differing distributions shown below:

par(mfrow=c(3, 1))
par(mar=rep(2, 4))
plot(density(iris$Sepal.Length[iris$Species=="setosa"]), main="Sepal Length: setosa", col="green")
plot(density(iris$Sepal.Length[iris$Species=="versicolor"]), main="Sepal Length: versicolor", col="blue")
plot(density(iris$Sepal.Length[iris$Species=="virginica"]), main="Sepal Length: virginica", col="palevioletred4")

par(mfrow=c(1, 1))

Comparing datasets

Neither of these plots above show the relative distribtions on the same scale, even if we match the x-axis of a density plot the relative heights are obscured and difficult to compare.

par(mfrow=c(3, 1))
par(mar=rep(2, 4))
xaxis <- c(3, 9)
yaxis <- c(0, 1.25)
plot(density(iris$Sepal.Length[iris$Species=="setosa"]), main="Sepal Length: setosa", col="green", xlim=xaxis, ylim=yaxis)
plot(density(iris$Sepal.Length[iris$Species=="versicolor"]), main="Sepal Length: versicolor", col="blue", xlim=xaxis, ylim=yaxis)
plot(density(iris$Sepal.Length[iris$Species=="virginica"]), main="Sepal Length: virginica", col="palevioletred4", xlim=xaxis, ylim=yaxis)

par(mfrow=c(1, 1))

This can somewhat be addressed by overlaying density plots:

par(mfrow=c(1, 1))
xaxis <- c(3, 9)
yaxis <- c(0, 1.25)
plot(density(iris$Sepal.Length[iris$Species=="setosa"]), main="Sepal Length", col="green", xlim=xaxis, ylim=yaxis)
lines(density(iris$Sepal.Length[iris$Species=="versicolor"]), col="blue")
lines(density(iris$Sepal.Length[iris$Species=="virginica"]), col="palevioletred4")
legend("topright", fill=c("green", "blue", "palevioletred4"), legend=levels(iris$Species), cex=0.5)

This has the benefit of highlighting the differnt distributions of the data subsets. However, notice here that a figure legend become necessary, plot axis limits need to be defined to display the range of all distribution curves, and the plot quickly becomes cluttered if the number of factors to be compared becomes much larger.

Area control in Violin plot

Therefore the areaEqual parameter has been echod to customise the violin plot to serve a similar purpose:

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", areaEqual = T)

If we compare this to the original vioplot functionality (defaulting to areaEqual = FALSE) the differences between the two are clear.

par(mfrow=c(2,1))
par(mar=rep(2, 4))
vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Width)", areaEqual = F)
vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T)

par(mfrow=c(1,1))

Note that areaEqual is considering the full area of the density distribution before removing the outlier tails. We leave it up to the users discretion which they elect to use. The areaEqual functionality is compatible with all of the customisation used in discussed in the main vioplot vignette

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T, col=c("lightgreen", "lightblue", "palevioletred"), rectCol=c("green", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), border=c("darkolivegreen4", "royalblue4", "violetred4"))

The violin width can further be scaled with wex, which maintains the proportions across the datasets if areaEqual = TRUE:

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T, col=c("lightgreen", "lightblue", "palevioletred"), rectCol=c("green", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), border=c("darkolivegreen4", "royalblue4", "violetred4"), wex=1.25)

Comparing distributions

Notice the utility of areaEqual for cases where different datasets have different underlying distributions:

vioplot(rnorm(200, 3, 0.5), rpois(200, 2.5),  rbinom(100, 10, 0.4), rlnorm(200, 0, 0.5), rnbinom(200, 10, 0.9), rlogis(20, 0, 0.5), areaEqual = F, main="Equal Width", xlab="distribution", ylab="data value", names=c("normal", "poisson", "binomial", "log-normal", "neg-binomial", "logistic"))

vioplot(rnorm(200, 3, 0.5), rpois(200, 2.5),  rbinom(100, 10, 0.4), rlnorm(200, 0, 0.5), rnbinom(200, 10, 0.9), rlogis(20, 0, 0.5), areaEqual = T, main="Equal Area", xlab="distribution", ylab="data value", names=c("normal", "poisson", "binomial", "log-normal", "neg-binomial", "logistic"))

vioplot/vignettes/backup/violin_area.Rmd0000644000176200001440000001714213507652102020165 0ustar liggesusers--- title: "Controlling Violin Plot Area" author: "Tom Kelly" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{vioplot: Controlling Violin Plot Area} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- While boxplots have become the _de facto_ standard for plotting the distribution of data this is a vast oversimplification and may not show everything needed to evaluate the variation of data. This is particularly important for datasets which do not form a Gaussian "Normal" distribution that most researchers have become accustomed to. While density plots are helpful in this regard, they can be less aesthetically pleasing than boxplots and harder to interpret for those familiar with boxplots. Often the only ways to compare multiple data types with density use slices of the data with faceting the plotting panes or overlaying density curves with colours and a legend. This approach is jarring for new users and leads to cluttered plots difficult to present to a wider audience. ##Violin Plots Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits: - Greater flexibility for plotting variation than boxplots - More familiarity to boxplot users than density plots - Easier to directly compare data types than existing plots As shown below for the `iris` dataset, violin plots show distribution information that the boxplot is unable to. ```{r} library("vioplot") ``` ```{r, message=FALSE} data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) ``` ##Violin Plot Area However there are concerns that existing violin plot packages (such as \code{\link[vioplot]{vioplot}}) scales the data to the most aesthetically suitable width rather than maintaining proportions comparable across data sets. Consider the differing distributions shown below: ```{r, echo=FALSE, message=FALSE} par(mar=rep(1,4)) ``` ```{r} par(mfrow=c(3, 1)) par(mar=rep(2, 4)) plot(density(iris$Sepal.Length[iris$Species=="setosa"]), main="Sepal Length: setosa", col="green") plot(density(iris$Sepal.Length[iris$Species=="versicolor"]), main="Sepal Length: versicolor", col="blue") plot(density(iris$Sepal.Length[iris$Species=="virginica"]), main="Sepal Length: virginica", col="palevioletred4") par(mfrow=c(1, 1)) ``` ```{r, echo=FALSE, message=FALSE} par(mar=c(5, 4, 4, 2) + 0.1) ``` #Comparing datasets Neither of these plots above show the relative distributions on the same scale, even if we match the x-axis of a density plot the relative heights are obscured and difficult to compare. ```{r, echo=FALSE, message=FALSE} par(mar=rep(2,4)) ``` ```{r} par(mfrow=c(3, 1)) par(mar=rep(2, 4)) xaxis <- c(3, 9) yaxis <- c(0, 1.25) plot(density(iris$Sepal.Length[iris$Species=="setosa"]), main="Sepal Length: setosa", col="green", xlim=xaxis, ylim=yaxis) plot(density(iris$Sepal.Length[iris$Species=="versicolor"]), main="Sepal Length: versicolor", col="blue", xlim=xaxis, ylim=yaxis) plot(density(iris$Sepal.Length[iris$Species=="virginica"]), main="Sepal Length: virginica", col="palevioletred4", xlim=xaxis, ylim=yaxis) par(mfrow=c(1, 1)) ``` ```{r, echo=FALSE, message=FALSE} par(mar=c(5, 4, 4, 2) + 0.1) ``` This can somewhat be addressed by overlaying density plots: ```{r} par(mfrow=c(1, 1)) xaxis <- c(3, 9) yaxis <- c(0, 1.25) plot(density(iris$Sepal.Length[iris$Species=="setosa"]), main="Sepal Length", col="green", xlim=xaxis, ylim=yaxis) lines(density(iris$Sepal.Length[iris$Species=="versicolor"]), col="blue") lines(density(iris$Sepal.Length[iris$Species=="virginica"]), col="palevioletred4") legend("topright", fill=c("green", "blue", "palevioletred4"), legend=levels(iris$Species), cex=0.5) ``` This has the benefit of highlighting the different distributions of the data subsets. However, notice here that a figure legend become necessary, plot axis limits need to be defined to display the range of all distribution curves, and the plot quickly becomes cluttered if the number of factors to be compared becomes much larger. ##Area control in Violin plot Therefore the `areaEqual` parameter has been added to customise the violin plot to serve a similar purpose: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", areaEqual = T) ``` If we compare this to the original vioplot functionality (defaulting to `areaEqual = FALSE`) the differences between the two are clear. ```{r, echo=FALSE, message=FALSE} par(mar=rep(2, 4)) ``` ```{r} par(mfrow=c(2,1)) par(mar=rep(2, 4)) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Width)", areaEqual = F) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T) par(mfrow=c(1,1)) ``` ```{r, echo=FALSE, message=FALSE} par(mar=c(5, 4, 4, 2) + 0.1) ``` Note that `areaEqual` is considering the full area of the density distribution before removing the outlier tails. We leave it up to the users discretion which they elect to use. The `areaEqual` functionality is compatible with all of the customisation used in discussed in [the main vioplot vignette](violin_customisation.html) ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T, col=c("lightgreen", "lightblue", "palevioletred"), rectCol=c("green", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), border=c("darkolivegreen4", "royalblue4", "violetred4")) ``` The violin width can further be scaled with `wex`, which maintains the proportions across the datasets if `areaEqual = TRUE`: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T, col=c("lightgreen", "lightblue", "palevioletred"), rectCol=c("green", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), border=c("darkolivegreen4", "royalblue4", "violetred4"), wex=1.25) ``` ## Comparing distributions Notice the utility of `areaEqual` for cases where different datasets have different underlying distributions: ```{r} vioplot(rnorm(200, 3, 0.5), rpois(200, 2.5), rbinom(100, 10, 0.4), rlnorm(200, 0, 0.5), rnbinom(200, 10, 0.9), rlogis(20, 0, 0.5), areaEqual = F, main="Equal Width", xlab="distribution", ylab="data value", names=c("normal", "poisson", "binomial", "log-normal", "neg-binomial", "logistic")) vioplot(rnorm(200, 3, 0.5), rpois(200, 2.5), rbinom(100, 10, 0.4), rlnorm(200, 0, 0.5), rnbinom(200, 10, 0.9), rlogis(20, 0, 0.5), areaEqual = T, main="Equal Area", xlab="distribution", ylab="data value", names=c("normal", "poisson", "binomial", "log-normal", "neg-binomial", "logistic")) ``` vioplot/vignettes/backup/violin_formulae.html0000755000176200001440000547060213320630501021315 0ustar liggesusers Customising Violin Plots

Since boxplots have become the de facto standard for plotting the distribution of data most users are familiar with these and the formula input for dataframes. However this input is not available in the standard vioplot package. Thus it has been restored here for enhanced backwards compatibility with boxplot.

As shown below for the iris dataset, violin plots show distribution information taking formula input that boxplot implements but vioplot is unable to. This demonstrates the customisation demonstrated in the main vioplot vignette using vioplot syntax with the formula method commonly used for boxplot, t.test, and lm.

data(iris)
boxplot(Sepal.Length~Species, data = iris)

Whereas performing the same function does not work with vioplot.

library("vioplot")
vioplot(Sepal.Length~Species, data = iris)
Error in min(data) : invalid 'type' (language) of argument

Plot Defaults

vioplot(Sepal.Length~Species, data = iris)

Another concern we see here is that the vioplot defaults are not aesthetically pleasing, with a rather glaring colour scheme unsuitable for professional or academic usage. Thus the plot default colours have been changed as shown here:

vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length")

Plot colours: Violin Fill

Plot colours can be further customised as with the original vioplot package using the col argument:

vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col="lightblue")

Vectorisation

However the vioplot function is unable to colour each violin separately, thus this is enabled with a vectorised col in vioplot:

vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col=c("lightgreen", "lightblue", "palevioletred"))
legend("topleft", legend=c("setosa", "versicolor", "virginica"), fill=c("lightgreen", "lightblue", "palevioletred"), cex = 0.5)

Plot colours: Violin Lines and Boxplot

Colours can also be customised for the violin fill and border separately using the col and border arguments:

vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col="lightblue", border="royalblue")

Similarly, the arguments lineCol and rectCol specify the colors of the boxplot outline and rectangle fill. For simplicity the box and whiskers of the boxplot will always have the same colour.

vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", rectCol="palevioletred", lineCol="violetred")

The same applies to the colour of the median point with colMed:

vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", colMed="violet")

### Combined customisation

These can be customised colours can be combined:

vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col="lightblue", border="royalblue", rectCol="palevioletred", lineCol="violetred", colMed="violet")

Vectorisation

These color and shape settings can also be customised separately for each violin:

vioplot(Sepal.Length~Species, data = iris, main="Sepal Length (Equal Area)", areaEqual = T, col=c("lightgreen", "lightblue", "palevioletred"), border=c("darkolivegreen4", "royalblue4", "violetred4"), rectCol=c("forestgreen", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), colMed=c("green", "cyan", "magenta"), pchMed=c(15, 17, 19))

vioplot/vignettes/backup/violin_ylog.html0000755000176200001440000350530213320630501020447 0ustar liggesusers Controlling y-axis Plotting

While boxplots have become the de facto standard for plotting the distribution of data this is a vast oversimplification and may not show everything needed to evaluate the variation of data. This is particularly important for datasets which do not form a Guassian “Normal” distribution that most researchers have become accustomed to.

While density plots are helpful in this regard, they can be less aesthetically pleasing than boxplots and harder to interpret for those familiar with boxplots. Often the only ways to compare multiple data types with density use slices of the data with faceting the plotting panes or overlaying density curves with colours and a legend. This approach is jarring for new users and leads to cluttered plots difficult to present to a wider audience.

Violin Plots

Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits:

  • Greater flexbility for plotting variation than boxplots
  • More familiarity to boxplot users than density plots
  • Easier to directly compare data types than existing plots

As shown below for the iris dataset, violin plots show distribution information that the boxplot is unable to.

data(iris)
boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"))

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"))

Violin y-axis

Logarithmic scale

However the existing violin plot packages (such as ) do not support log-scale of the y-axis. This has been ammended with the ylog argument.

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", ylog = T, ylim=c(log(1), log(10)))

This can also be invoked with the log="y" argument compatble with boxplot:

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = T, ylim=c(log(1), log(10)))
vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = "y", ylim=c(log(1), log(10)))

custom y-axes

The y-axes can also be removed with yaxt="n" to enable customised y-axes:

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", yaxt="n")

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", ylog = T, yaxt="n", ylim=c(log(1), log(10)))

Thus custom axes can be added to violin plots. As shown on a linear scale:

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", yaxt="n")
axis(2, at=1:10, labels=1:10)

As well as for on a log scale:

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", yaxt="n", log="y", ylim=c(log(4), log(9)))
axis(2, at=log(1:10), labels=1:10)

vioplot/vignettes/backup/violin_customisation.html0000755000176200001440000547574413320630501022420 0ustar liggesusers Customising Violin Plots

While boxplots have become the de facto standard for plotting the distribution of data this is a vast oversimplification and may not show everything needed to evaluate the variation of data. This is particularly important for datasets which do not form a Guassian “Normal” distribution that most researchers have become accustomed to.

While density plots are helpful in this regard, they can be less aesthetically pleasing than boxplots and harder to interpret for those familiar with boxplots. Often the only ways to compare multiple data types with density use slices of the data with faceting the plotting panes or overlaying density curves with colours and a legend. This approach is jarring for new users and leads to cluttered plots difficult to present to a wider audience.

Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits:

  • Greater flexbility for plotting variation than boxplots
  • More familiarity to boxplot users than density plots
  • Easier to directly compare data types than existing plots

As shown below for the iris dataset, violin plots show distribution information that the boxplot is unable to.

data(iris)
boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"))
library("vioplot")
vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"))

Plot Defaults

However as we can see here the plot defaults are not aesthetically pleasing, with a rather glaring colour scheme unsuitable for professional or academic usage. Thus the plot default colours have been changed as shown here:

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length")

Plot colours: Violin Fill

Plot colours can be further customised as with the original vioplot package using the col argument:

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue")

Vectorisation

However the vioplot function is unable to colour each violin separately, thus this is enabled with a vectorised col in vioplot:

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col=c("lightgreen", "lightblue", "palevioletred"))
legend("topleft", legend=c("setosa", "versicolor", "virginica"), fill=c("lightgreen", "lightblue", "palevioletred"), cex = 0.5)

Plot colours: Violin Lines and Boxplot

Colours can also be customised for the violin fill and border separately using the col and border arguments:

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue", border="royalblue")

Similarly, the arguments lineCol and rectCol specify the colors of the boxplot outline and rectangle fill. For simplicity the box and whiskers of the boxplot will always have the same colour.

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", rectCol="palevioletred", lineCol="violetred")

The same applies to the colour of the median point with colMed:

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", colMed="violet")

### Combined customisation

These can be customised colours can be combined:

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue", border="royalblue", rectCol="palevioletred", lineCol="violetred", colMed="violet")

Vectorisation

These color and shape settings can also be customised separately for each violin:

vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T, col=c("lightgreen", "lightblue", "palevioletred"), border=c("darkolivegreen4", "royalblue4", "violetred4"), rectCol=c("forestgreen", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), colMed=c("green", "cyan", "magenta"), pchMed=c(15, 17, 19))

This should be sufficient to customise the violin plot but further examples are given in the areaEqual vioplot vignette including how violin plots are useful for comparing variation when data does not follow the same distribution. This document also compares the violin plot with other established methods to plot data variation.

vioplot/vignettes/backup/violin_customisation.Rmd0000644000176200001440000001453413507651667022177 0ustar liggesusers--- title: "Customising Violin Plots" author: "Tom Kelly" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{vioplot: Customising Violin Plots} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- While boxplots have become the _de facto_ standard for plotting the distribution of data this is a vast oversimplification and may not show everything needed to evaluate the variation of data. This is particularly important for datasets which do not form a Gaussian "Normal" distribution that most researchers have become accustomed to. While density plots are helpful in this regard, they can be less aesthetically pleasing than boxplots and harder to interpret for those familiar with boxplots. Often the only ways to compare multiple data types with density use slices of the data with faceting the plotting panes or overlaying density curves with colours and a legend. This approach is jarring for new users and leads to cluttered plots difficult to present to a wider audience. Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits: - Greater flexbility for plotting variation than boxplots - More familiarity to boxplot users than density plots - Easier to directly compare data types than existing plots As shown below for the `iris` dataset, violin plots show distribution information that the boxplot is unable to. ```{r} library("vioplot") ``` ```{r, message=FALSE, eval=FALSE} data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) library("vioplot") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) ``` ```{r, message=FALSE, echo=FALSE} data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="magenta") ``` ## Plot Defaults However as we can see here the plot defaults are not aesthetically pleasing, with a rather glaring colour scheme unsuitable for professional or academic usage. Thus the plot default colours have been changed as shown here: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length") ``` ## Plot colours: Violin Fill Plot colours can be further customised as with the original vioplot package using the `col` argument: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue") ``` ### Vectorisation However the `vioplot` (0.2) function is unable to colour each violin separately, thus this is enabled with a vectorised `col` in `vioplot` (0.3): ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col=c("lightgreen", "lightblue", "palevioletred")) legend("topleft", legend=c("setosa", "versicolor", "virginica"), fill=c("lightgreen", "lightblue", "palevioletred"), cex = 0.5) ``` ## Plot colours: Violin Lines and Boxplot Colours can also be customised for the violin fill and border separately using the `col` and `border` arguments: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue", border="royalblue") ``` Similarly, the arguments `lineCol` and `rectCol` specify the colours of the boxplot outline and rectangle fill. For simplicity the box and whiskers of the boxplot will always have the same colour. ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", rectCol="palevioletred", lineCol="violetred") ``` The same applies to the colour of the median point with `colMed`: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", colMed="violet") ``` ### Combined customisation These can be customised colours can be combined: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue", border="royalblue", rectCol="palevioletred", lineCol="violetred", colMed="violet") ``` ### Vectorisation These colour and shape settings can also be customised separately for each violin: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T, col=c("lightgreen", "lightblue", "palevioletred"), border=c("darkolivegreen4", "royalblue4", "violetred4"), rectCol=c("forestgreen", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), colMed=c("green", "cyan", "magenta"), pchMed=c(15, 17, 19)) ``` This should be sufficient to customise the violin plot but further examples are given in [the areaEqual vioplot vignette](violin_area.html) including how violin plots are useful for comparing variation when data does not follow the same distribution. This document also compares the violin plot with other established methods to plot data variation. vioplot/vignettes/violin_ylog.Rmd0000755000176200001440000001031613507766533016777 0ustar liggesusers--- title: "Controlling y-axis Plotting" author: "Tom Kelly" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{vioplot: Controlling y-axis Plotting} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- While boxplots have become the _de facto_ standard for plotting the distribution of data this is a vast oversimplification and may not show everything needed to evaluate the variation of data. This is particularly important for datasets which do not form a Gaussian "Normal" distribution that most researchers have become accustomed to. While density plots are helpful in this regard, they can be less aesthetically pleasing than boxplots and harder to interpret for those familiar with boxplots. Often the only ways to compare multiple data types with density use slices of the data with faceting the plotting panes or overlaying density curves with colours and a legend. This approach is jarring for new users and leads to cluttered plots difficult to present to a wider audience. ##Violin Plots Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits: - Greater flexibility for plotting variation than boxplots - More familiarity to boxplot users than density plots - Easier to directly compare data types than existing plots As shown below for the `iris` dataset, violin plots show distribution information that the boxplot is unable to. ```{r} library("vioplot") ``` ```{r, message=FALSE} data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) ``` ##Violin y-axis ###Logarithmic scale However the existing violin plot packages (such as \code{\link[vioplot]{vioplot}}) do not support log-scale of the y-axis. This has been amended with the `ylog` argument. ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", ylog = T, ylim=c(log(1), log(10))) ``` This can also be invoked with the `log="y"` argument compatible with `boxplot`: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = T, ylim=c(log(1), log(10))) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = "y", ylim=c(log(1), log(10))) ``` ###custom y-axes The y-axes can also be removed with `yaxt="n"` to enable customised y-axes: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", yaxt="n") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", ylog = T, yaxt="n", ylim=c(log(1), log(10))) ``` Thus custom axes can be added to violin plots. As shown on a linear scale: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", yaxt="n") axis(2, at=1:10, labels=1:10) ``` As well as for on a log scale: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", yaxt="n", log="y", ylim=c(log(4), log(9))) axis(2, at=log(1:10), labels=1:10) ``` vioplot/vignettes/violin_area.Rmd0000755000176200001440000001714113507652105016725 0ustar liggesusers--- title: "Controlling Violin Plot Area" author: "Tom Kelly" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{vioplot: Controlling Violin Plot Area} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- While boxplots have become the _de facto_ standard for plotting the distribution of data this is a vast oversimplification and may not show everything needed to evaluate the variation of data. This is particularly important for datasets which do not form a Gaussian "Normal" distribution that most researchers have become accustomed to. While density plots are helpful in this regard, they can be less aesthetically pleasing than boxplots and harder to interpret for those familiar with boxplots. Often the only ways to compare multiple data types with density use slices of the data with faceting the plotting panes or overlaying density curves with colours and a legend. This approach is jarring for new users and leads to cluttered plots difficult to present to a wider audience. ##Violin Plots Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits: - Greater flexibility for plotting variation than boxplots - More familiarity to boxplot users than density plots - Easier to directly compare data types than existing plots As shown below for the `iris` dataset, violin plots show distribution information that the boxplot is unable to. ```{r} library("vioplot") ``` ```{r, message=FALSE} data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) ``` ##Violin Plot Area However there are concerns that existing violin plot packages (such as \code{\link[vioplot]{vioplot}}) scales the data to the most aesthetically suitable width rather than maintaining proportions comparable across data sets. Consider the differing distributions shown below: ```{r, echo=FALSE, message=FALSE} par(mar=rep(1,4)) ``` ```{r} par(mfrow=c(3, 1)) par(mar=rep(2, 4)) plot(density(iris$Sepal.Length[iris$Species=="setosa"]), main="Sepal Length: setosa", col="green") plot(density(iris$Sepal.Length[iris$Species=="versicolor"]), main="Sepal Length: versicolor", col="blue") plot(density(iris$Sepal.Length[iris$Species=="virginica"]), main="Sepal Length: virginica", col="palevioletred4") par(mfrow=c(1, 1)) ``` ```{r, echo=FALSE, message=FALSE} par(mar=c(5, 4, 4, 2) + 0.1) ``` #Comparing datasets Neither of these plots above show the relative distribtions on the same scale, even if we match the x-axis of a density plot the relative heights are obscured and difficult to compare. ```{r, echo=FALSE, message=FALSE} par(mar=rep(2,4)) ``` ```{r} par(mfrow=c(3, 1)) par(mar=rep(2, 4)) xaxis <- c(3, 9) yaxis <- c(0, 1.25) plot(density(iris$Sepal.Length[iris$Species=="setosa"]), main="Sepal Length: setosa", col="green", xlim=xaxis, ylim=yaxis) plot(density(iris$Sepal.Length[iris$Species=="versicolor"]), main="Sepal Length: versicolor", col="blue", xlim=xaxis, ylim=yaxis) plot(density(iris$Sepal.Length[iris$Species=="virginica"]), main="Sepal Length: virginica", col="palevioletred4", xlim=xaxis, ylim=yaxis) par(mfrow=c(1, 1)) ``` ```{r, echo=FALSE, message=FALSE} par(mar=c(5, 4, 4, 2) + 0.1) ``` This can somewhat be addressed by overlaying density plots: ```{r} par(mfrow=c(1, 1)) xaxis <- c(3, 9) yaxis <- c(0, 1.25) plot(density(iris$Sepal.Length[iris$Species=="setosa"]), main="Sepal Length", col="green", xlim=xaxis, ylim=yaxis) lines(density(iris$Sepal.Length[iris$Species=="versicolor"]), col="blue") lines(density(iris$Sepal.Length[iris$Species=="virginica"]), col="palevioletred4") legend("topright", fill=c("green", "blue", "palevioletred4"), legend=levels(iris$Species), cex=0.5) ``` This has the benefit of highlighting the different distributions of the data subsets. However, notice here that a figure legend become necessary, plot axis limits need to be defined to display the range of all distribution curves, and the plot quickly becomes cluttered if the number of factors to be compared becomes much larger. ##Area control in Violin plot Therefore the `areaEqual` parameter has been added to customise the violin plot to serve a similar purpose: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", areaEqual = T) ``` If we compare this to the original vioplot functionality (defaulting to `areaEqual = FALSE`) the differences between the two are clear. ```{r, echo=FALSE, message=FALSE} par(mar=rep(2, 4)) ``` ```{r} par(mfrow=c(2,1)) par(mar=rep(2, 4)) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Width)", areaEqual = F) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T) par(mfrow=c(1,1)) ``` ```{r, echo=FALSE, message=FALSE} par(mar=c(5, 4, 4, 2) + 0.1) ``` Note that `areaEqual` is considering the full area of the density distribution before removing the outlier tails. We leave it up to the users discretion which they elect to use. The `areaEqual` functionality is compatible with all of the customisation used in discussed in [the main vioplot vignette](violin_customisation.html) ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T, col=c("lightgreen", "lightblue", "palevioletred"), rectCol=c("green", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), border=c("darkolivegreen4", "royalblue4", "violetred4")) ``` The violin width can further be scaled with `wex`, which maintains the proportions across the datasets if `areaEqual = TRUE`: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T, col=c("lightgreen", "lightblue", "palevioletred"), rectCol=c("green", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), border=c("darkolivegreen4", "royalblue4", "violetred4"), wex=1.25) ``` ## Comparing distributions Notice the utility of `areaEqual` for cases where different datasets have different underlying distributions: ```{r} vioplot(rnorm(200, 3, 0.5), rpois(200, 2.5), rbinom(100, 10, 0.4), rlnorm(200, 0, 0.5), rnbinom(200, 10, 0.9), rlogis(20, 0, 0.5), areaEqual = F, main="Equal Width", xlab="distribution", ylab="data value", names=c("normal", "poisson", "binomial", "log-normal", "neg-binomial", "logistic")) vioplot(rnorm(200, 3, 0.5), rpois(200, 2.5), rbinom(100, 10, 0.4), rlnorm(200, 0, 0.5), rnbinom(200, 10, 0.9), rlogis(20, 0, 0.5), areaEqual = T, main="Equal Area", xlab="distribution", ylab="data value", names=c("normal", "poisson", "binomial", "log-normal", "neg-binomial", "logistic")) ``` vioplot/vignettes/violin_formulae.Rmd0000755000176200001440000001011013507766533017627 0ustar liggesusers--- title: "Customising Violin Plots with Formula Input" author: "Tom Kelly" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{vioplot: Customising Violin Plots with Formula Input} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- Since boxplots have become the _de facto_ standard for plotting the distribution of data most users are familiar with these and the formula input for dataframes. However this input is not available in the standard `vioplot` package. Thus it has been restored here for enhanced backwards compatibility with `boxplot`. As shown below for the `iris` dataset, violin plots show distribution information taking formula input that `boxplot` implements but `vioplot` is unable to. This demonstrates the customisation demonstrated in [the main vioplot vignette using vioplot syntax](violin_customisation.html) with the formula method commonly used for `boxplot`, `t.test`, and `lm`. ```{r} library("vioplot") ``` ```{r, message=FALSE, eval=FALSE} data(iris) boxplot(Sepal.Length~Species, data = iris) ``` ```{r, message=FALSE, echo=FALSE} data(iris) boxplot(Sepal.Length~Species, data = iris, main = "Sepal Length") ``` Whereas performing the same function does not work with `vioplot` (0.2). ```{r, message=FALSE, eval=FALSE} devtools::install_version("vioplot", version = "0.2") library("vioplot") vioplot(Sepal.Length~Species, data = iris) ``` ``` Error in min(data) : invalid 'type' (language) of argument ``` ## Plot Defaults ```{r, message=FALSE, eval=FALSE} vioplot(Sepal.Length~Species, data = iris) ``` ```{r, message=FALSE, echo=FALSE} vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col="magenta") ``` Another concern we see here is that the `vioplot` defaults are not aesthetically pleasing, with a rather glaring colour scheme unsuitable for professional or academic usage. Thus the plot default colours have been changed as shown here: ```{r} vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length") ``` ## Plot colours: Violin Fill Plot colours can be further customised as with the original vioplot package using the `col` argument: ```{r} vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col="lightblue") ``` ### Vectorisation However the `vioplot` (0.2) function is unable to colour each violin separately, thus this is enabled with a vectorised `col` in `vioplot` (0.3): ```{r} vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col=c("lightgreen", "lightblue", "palevioletred")) legend("topleft", legend=c("setosa", "versicolor", "virginica"), fill=c("lightgreen", "lightblue", "palevioletred"), cex = 0.5) ``` ## Plot colours: Violin Lines and Boxplot Colours can also be customised for the violin fill and border separately using the `col` and `border` arguments: ```{r} vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col="lightblue", border="royalblue") ``` Similarly, the arguments `lineCol` and `rectCol` specify the colours of the boxplot outline and rectangle fill. For simplicity the box and whiskers of the boxplot will always have the same colour. ```{r} vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", rectCol="palevioletred", lineCol="violetred") ``` The same applies to the colour of the median point with `colMed`: ```{r} vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", colMed="violet") ``` ### Combined customisation These can be customised colours can be combined: ```{r} vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col="lightblue", border="royalblue", rectCol="palevioletred", lineCol="violetred", colMed="violet") ``` ### Vectorisation These colour and shape settings can also be customised separately for each violin: ```{r} vioplot(Sepal.Length~Species, data = iris, main="Sepal Length", col=c("lightgreen", "lightblue", "palevioletred"), border=c("darkolivegreen4", "royalblue4", "violetred4"), rectCol=c("forestgreen", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), colMed=c("green", "cyan", "magenta"), pchMed=c(15, 17, 19)) ``` vioplot/vignettes/violin_customisation.Rmd0000755000176200001440000001453313507766533020733 0ustar liggesusers--- title: "Customising Violin Plots" author: "Tom Kelly" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{vioplot: Customising Violin Plots} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- While boxplots have become the _de facto_ standard for plotting the distribution of data this is a vast oversimplification and may not show everything needed to evaluate the variation of data. This is particularly important for datasets which do not form a Gaussian "Normal" distribution that most researchers have become accustomed to. While density plots are helpful in this regard, they can be less aesthetically pleasing than boxplots and harder to interpret for those familiar with boxplots. Often the only ways to compare multiple data types with density use slices of the data with faceting the plotting panes or overlaying density curves with colours and a legend. This approach is jarring for new users and leads to cluttered plots difficult to present to a wider audience. Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits: - Greater flexibility for plotting variation than boxplots - More familiarity to boxplot users than density plots - Easier to directly compare data types than existing plots As shown below for the `iris` dataset, violin plots show distribution information that the boxplot is unable to. ```{r} library("vioplot") ``` ```{r, message=FALSE, eval=FALSE} data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) library("vioplot") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) ``` ```{r, message=FALSE, echo=FALSE} data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="magenta") ``` ## Plot Defaults However as we can see here the plot defaults are not aesthetically pleasing, with a rather glaring colour scheme unsuitable for professional or academic usage. Thus the plot default colours have been changed as shown here: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length") ``` ## Plot colours: Violin Fill Plot colours can be further customised as with the original vioplot package using the `col` argument: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue") ``` ### Vectorisation However the `vioplot` (0.2) function is unable to colour each violin separately, thus this is enabled with a vectorised `col` in `vioplot` (0.3): ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col=c("lightgreen", "lightblue", "palevioletred")) legend("topleft", legend=c("setosa", "versicolor", "virginica"), fill=c("lightgreen", "lightblue", "palevioletred"), cex = 0.5) ``` ## Plot colours: Violin Lines and Boxplot Colours can also be customised for the violin fill and border separately using the `col` and `border` arguments: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue", border="royalblue") ``` Similarly, the arguments `lineCol` and `rectCol` specify the colors of the boxplot outline and rectangle fill. For simplicity the box and whiskers of the boxplot will always have the same colour. ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", rectCol="palevioletred", lineCol="violetred") ``` The same applies to the colour of the median point with `colMed`: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", colMed="violet") ``` ### Combined customisation These can be customised colours can be combined: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue", border="royalblue", rectCol="palevioletred", lineCol="violetred", colMed="violet") ``` ### Vectorisation These color and shape settings can also be customised separately for each violin: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T, col=c("lightgreen", "lightblue", "palevioletred"), border=c("darkolivegreen4", "royalblue4", "violetred4"), rectCol=c("forestgreen", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), colMed=c("green", "cyan", "magenta"), pchMed=c(15, 17, 19)) ``` This should be sufficient to customise the violin plot but further examples are given in [the areaEqual vioplot vignette](violin_area.html) including how violin plots are useful for comparing variation when data does not follow the same distribution. This document also compares the violin plot with other established methods to plot data variation. vioplot/R/0000755000176200001440000000000013570226443012155 5ustar liggesusersvioplot/R/vioplot.R0000755000176200001440000006104713570226443014007 0ustar liggesusers#' violin plot #' #' Produce violin plot(s) of the given (grouped) values with enhanced annotation and colour per group. Includes customisation of colours for each aspect of the violin, boxplot, and separate violins. This supports input of data as a list or formula, being backwards compatible with \code{\link[vioplot]{vioplot}} (0.2) and taking input in a formula as used for \code{\link[graphics]{boxplot}}. #' #' @param x for specifying data from which the boxplots are to be produced. Either a numeric vector, or a single list containing such vectors. Additional unnamed arguments specify further data as separate vectors (each corresponding to a component boxplot). NAs are allowed in the data. #' @param ... additional data vectors or formula parameters. For the formula method, named arguments to be passed to the default method. #' @param formula a formula, such as y ~ grp, where y is a numeric vector of data values to be split into groups according to the grouping variable grp (usually a factor). #' @param data a data.frame (or list) from which the variables in formula should be taken. #' @param subset an optional vector specifying a subset of observations to be used for plotting. #' @param drop,sep,lex.order defines groups to plot from formula, passed to \code{\link[base]{split.default}}, see there. #' @param range a factor to calculate the upper/lower adjacent values #' @param h the height for the density estimator, if omit as explained in sm.density, h will be set to an optimum #' @param ylim y limits #' @param yaxt A character which specifies the y axis type. Specifying "n" suppresses plotting. #' @param ylog A logical value (see log in \code{\link[graphics]{plot.default}}). If TRUE, a logarithmic scale is in use (e.g., after plot(*, log = "y")). For a new device, it defaults to FALSE, i.e., linear scale. #' @param log Logarithmic scale if log = "y" or TRUE. Invokes ylog = TRUE. #' @param logLab Increments for labelling y-axis on log-scale, defaults to numbers starting with 1, 2, 5, and 10. #' @param names one label, or a vector of labels for the data must match the number of data given #' @param col Graphical parameter for fill colour of the violin(s) polygon. NA for no fill colour. If col is a vector, it specifies the colour per violin, and colours are reused if necessary. #' @param border Graphical parameters for the colour of the violin border passed to lines. NA for no border. If border is a vector, it specifies the colour per violin, and colours are reused if necessary. #' @param lty,lwd Graphical parameters for the violin passed to lines and polygon #' @param rectCol Graphical parameters to control fill colour of the box. NA for no fill colour. If col is a vector, it specifies the colour per violin, and colours are reused if necessary. #' @param lineCol Graphical parameters to control colour of the box outline and whiskers. NA for no border. If lineCol is a vector, it specifies the colour per violin, and colours are reused if necessary. #' @param pchMed Graphical parameters to control shape of the median point. If pchMed is a vector, it specifies the shape per violin. #' @param colMed,colMed2 Graphical parameters to control colour of the median point. If colMed is a vector, it specifies the colour per violin. colMed specifies the fill colour in all cases unless pchMed is 21:25 in which case colMed is the border colour and colMed2 is the fill colour. #' @param drawRect logical. The box is drawn if TRUE. #' @param areaEqual logical. Density plots checked for equal area if TRUE. wex must be scalar, relative widths of violins depend on area. #' @param at position of each violin. Default to 1:n #' @param add logical. if FALSE (default) a new plot is created #' @param wex relative expansion of the violin. If wex is a vector, it specifies the area/width size per violin and sizes are reused if necessary. #' @param horizontal logical. horizontal or vertical violins #' @param main,sub,xlab,ylab graphical parameters passed to plot. #' @param cex A numerical value giving the amount by which plotting text should be magnified relative to the default. #' @param cex.axis The magnification to be used for y axis annotation relative to the current setting of cex. #' @param cex.names The magnification to be used for x axis annotation relative to the current setting of cex. Takes the value of cex.axis if not given. #' @param cex.lab The magnification to be used for x and y labels relative to the current setting of cex. #' @param cex.main The magnification to be used for main titles relative to the current setting of cex. #' @param cex.sub The magnification to be used for sub-titles relative to the current setting of cex. #' @param na.action a function which indicates what should happen when the data contain NAs. The default is to ignore missing values in either the response or the group. #' @param na.rm logical value indicating whether NA values should be stripped before the computation proceeds. Defaults to TRUE. #' @param side defaults to "both". Assigning "left" or "right" enables one sided plotting of violins. May be applied as a scalar across all groups. #' @param plotCentre defaults to "points", plotting a central point at the median. If "line" is given a median line is plotted (subject to side) alternatively. #' @param axes,frame.plot,panel.first,panel.last,asp,line,outer,adj,ann,ask,bg,bty,cin,col.axis,col.lab,col.main,col.sub,cra,crt,csi,cxy,din,err,family,fg,fig,fin,font,font.axis,font.lab,font.main,font.sub,lab,las,lend,lheight,ljoin,lmitre,mai,mar,mex,mfcol,mfg,mfrow,mgp,mkh,new,oma,omd,omi,page,pch,pin,plt,ps,pty,smo,srt,tck,tcl,usr,xlog,xaxp,xaxs,xaxt,xpd,yaxp,yaxs,ylbias Arguments to be passed to methods, such as graphical parameters (see \code{\link[graphics]{par}})). #' @keywords plot graphics violin #' @import sm #' @importFrom zoo rollmean #' @importFrom stats median na.omit quantile #' @importFrom graphics Axis axis box lines par plot.new plot.window plot.xy points polygon rect title #' @importFrom grDevices boxplot.stats dev.flush dev.hold dev.interactive devAskNewPage xy.coords #' @export #' @examples #' #' # box- vs violin-plot #' par(mfrow=c(2,1)) #' mu<-2 #' si<-0.6 #' bimodal<-c(rnorm(1000,-mu,si),rnorm(1000,mu,si)) #' uniform<-runif(2000,-4,4) #' normal<-rnorm(2000,0,3) #' vioplot(bimodal,uniform,normal) #' boxplot(bimodal,uniform,normal) #' #' # add to an existing plot #' x <- rnorm(100) #' y <- rnorm(100) #' plot(x, y, xlim=c(-5,5), ylim=c(-5,5)) #' vioplot(x, col="tomato", horizontal=TRUE, at=-4, add=TRUE,lty=2, rectCol="gray") #' vioplot(y, col="cyan", horizontal=FALSE, at=-4, add=TRUE,lty=2) #' #' # formula input #' data("iris") #' vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", #' col=c("lightgreen", "lightblue", "palevioletred")) #' legend("topleft", legend=c("setosa", "versicolor", "virginica"), #' fill=c("lightgreen", "lightblue", "palevioletred"), cex = 0.5) #' #' data("diamonds", package = "ggplot2") #' palette <- RColorBrewer::brewer.pal(9, "Pastel1") #' par(mfrow=c(3, 1)) #' vioplot(price ~ cut, data = diamonds, las = 1, col = palette) #' vioplot(price ~ clarity, data = diamonds, las = 2, col = palette) #' vioplot(price ~ color, data = diamonds, las = 2, col = palette) #' par(mfrow=c(3, 1)) #' #' #generate example data #' data_one <- rnorm(100) #' data_two <- rnorm(50, 1, 2) #' #' #generate violin plot with similar functionality to vioplot #' vioplot(data_one, data_two, col="magenta") #' #' #note vioplox defaults to a greyscale plot #' vioplot(data_one, data_two) #' #' #colours can be customised separately, with axis labels, legends, and titles #' vioplot(data_one, data_two, col=c("red","blue"), names=c("data one", "data two"), #' main="data violin", xlab="data class", ylab="data read") #' legend("topleft", fill=c("red","blue"), legend=c("data one", "data two")) #' #' #colours can be customised for the violin fill and border separately #' vioplot(data_one, data_two, col="grey85", border="purple", names=c("data one", "data two"), #' main="data violin", xlab="data class", ylab="data read") #' #' #colours can also be customised for the boxplot rectange and lines (border and whiskers) #' vioplot(data_one, data_two, col="grey85", rectCol="lightblue", lineCol="blue", #' border="purple", names=c("data one", "data two"), #' main="data violin", xlab="data class", ylab="data read") #' #' #these colours can also be customised separately for each violin #' vioplot(data_one, data_two, col=c("skyblue", "plum"), rectCol=c("lightblue", "palevioletred"), #' lineCol="blue", border=c("royalblue", "purple"), names=c("data one", "data two"), #' main="data violin", xlab="data class", ylab="data read") #' #' #this applies to any number of violins, given that colours are provided for each #' vioplot(data_one, data_two, rnorm(200, 3, 0.5), rpois(200, 2.5), rbinom(100, 10, 0.4), #' col=c("red", "orange", "green", "blue", "violet"), #' rectCol=c("palevioletred", "peachpuff", "lightgreen", "lightblue", "plum"), #' lineCol=c("red4", "orangered", "forestgreen", "royalblue", "mediumorchid"), #' border=c("red4", "orangered", "forestgreen", "royalblue", "mediumorchid"), #' names=c("data one", "data two", "data three", "data four", "data five"), #' main="data violin", xlab="data class", ylab="data read") #' #' #The areaEqual parameter scales with width of violins #' #Violins will have equal density area (including missing tails) rather than equal maximum width #' vioplot(data_one, data_two, areaEqual=TRUE) #' #' vioplot(data_one, data_two, areaEqual=TRUE, #' col=c("skyblue", "plum"), rectCol=c("lightblue", "palevioletred"), #' lineCol="blue", border=c("royalblue", "purple"), names=c("data one", "data two"), #' main="data violin", xlab="data class", ylab="data read") #' #' vioplot(data_one, data_two, rnorm(200, 3, 0.5), rpois(200, 2.5), rbinom(100, 10, 0.4), #' areaEqual=TRUE, col=c("red", "orange", "green", "blue", "violet"), #' rectCol=c("palevioletred", "peachpuff", "lightgreen", "lightblue", "plum"), #' lineCol=c("red4", "orangered", "forestgreen", "royalblue", "mediumorchid"), #' border=c("red4", "orangered", "forestgreen", "royalblue", "mediumorchid"), #' names=c("data one", "data two", "data three", "data four", "data five"), #' main="data violin", xlab="data class", ylab="data read") #' @export #' @usage NULL vioplot <- function(x, ...) { UseMethod("vioplot") } #' @rdname vioplot #' @export vioplot.formula <- function (formula, data = NULL, ..., subset, na.action = NULL, add = FALSE, ann = !add, horizontal = FALSE, xlab = mklab(y_var = horizontal), ylab = mklab(y_var = !horizontal), names=NULL, drop = FALSE, sep = ".", lex.order = FALSE) { if (missing(formula) || (length(formula) != 3L)) stop("'formula' missing or incorrect") if (missing(xlab) || missing(ylab)) mklab <- function(y_var) if (y_var) names(mf)[response] else paste(names(mf)[-response], collapse = " : ") m <- match.call(expand.dots = FALSE) if (is.matrix(eval(m$data, parent.frame()))) m$data <- as.data.frame(data) m$... <- m$drop <- m$sep <- m$lex.order <- NULL m$xlab <- m$ylab <- m$add <- m$ann <- m$horizontal <- NULL m$names <- NULL m$na.action <- na.action m[[1L]] <- quote(stats::model.frame.default) mf <- eval(m, parent.frame()) response <- attr(attr(mf, "terms"), "response") vioplot(split(mf[[response]], mf[-response], drop = drop, sep = sep, lex.order = lex.order), xlab = xlab, ylab = ylab, names = names, add = add, ann = ann, horizontal = horizontal, ...) } #' @rdname vioplot #' @export vioplot.default <- function (x, ..., data = NULL, range = 1.5, h = NULL, ylim = NULL, names = NULL, horizontal = FALSE, col = "grey50", border = par()$fg, lty = 1, lwd = 1, rectCol = par()$fg, lineCol = par()$fg, pchMed = 19, colMed = "white", colMed2 = "grey 75", at, add = FALSE, wex = 1, drawRect = TRUE, areaEqual=FALSE, axes = TRUE, frame.plot = axes, panel.first = NULL, panel.last = NULL, asp = NA, main="", sub="", xlab=NA, ylab=NA, line = NA, outer = FALSE, xlog = NA, ylog=NA, adj=NA, ann = NA, ask=NA, bg=NA, bty=NA, cex=NA, cex.axis=NA, cex.lab=NA, cex.main=NA, cex.names=NULL, cex.sub=NA, cin=NA, col.axis=NA, col.lab=NA, col.main=NA, col.sub=NA, cra=NA, crt=NA, csi=NA,cxy=NA, din=NA, err=NA, family=NA, fg=NA, fig=NA, fin=NA, font=NA, font.axis=NA, font.lab=NA, font.main=NA, font.sub=NA, lab=NA, las=NA, lend=NA, lheight=NA, ljoin=NA, lmitre=NA, mai=NA, mar=NA, mex=NA, mfcol=NA, mfg=NA, mfrow=NA, mgp=NA, mkh=NA, new=NA, oma=NA, omd=NA, omi=NA, page=NA, pch=NA, pin=NA, plt=NA, ps=NA, pty=NA, smo=NA, srt=NA, tck=NA, tcl=NA, usr=NA, xaxp=NA, xaxs=NA, xaxt=NA, xpd=NA, yaxp=NA, yaxs=NA, yaxt=NA, ylbias=NA, log="", logLab=c(1,2,5), na.action = NULL, na.rm = T, side = "both", plotCentre = "point") { #assign graphical parameters if not given for(ii in 1:length(names(par()))){ if(is.na(get(names(par())[ii])[1])) assign(names(par()[ii]), unlist(par()[[ii]])) } if(!is.list(x)){ datas <- list(x, ...) } else{ datas<-lapply(x, unlist) if(is.null(names)){ names <- names(datas) } } if(is.character(log)) if("y" %in% unlist(strsplit(log, ""))) log <- TRUE log <- ifelse(log == TRUE, "y", "") if(log == 'x' | log == 'xy' | xlog == TRUE){ if(horizontal | log == "xy"){ log <- TRUE } else { log <- FALSE ylog <- FALSE } xlog <- FALSE } if(log == TRUE | ylog == TRUE){ ylog <- TRUE log <- "y" } if(ylog){ #check data is compatible with log scale if(all(unlist(datas) <= 0)){ ylog <- FALSE warning("log scale cannot be used with non-positive data") } else { #log-scale data datas <- datas #lapply(datas, function(x) log(unlist(x))) } } if(is.null(na.action)) na.action <- na.omit lapply(datas, function(data) data <- data[!sapply(data, is.infinite)]) if(na.rm) datas <- lapply(datas, na.action) n <- length(datas) #if(is.list(datas)) datas <- as.data.frame(datas) if (missing(at)) at <- 1:n upper <- vector(mode = "numeric", length = n) lower <- vector(mode = "numeric", length = n) q1 <- vector(mode = "numeric", length = n) q2 <- vector(mode = "numeric", length = n) q3 <- vector(mode = "numeric", length = n) med <- vector(mode = "numeric", length = n) base <- vector(mode = "list", length = n) height <- vector(mode = "list", length = n) area_check <- vector(mode = "list", length = n) baserange <- c(Inf, -Inf) args <- list(display = "none") radj <- ifelse(side == "right", 0, 1) ladj <- ifelse(side == "left", 0, 1) boxwex <- wex if (!(is.null(h))) args <- c(args, h = h) if(plotCentre == "line") med.dens <- rep(NA, n) if(areaEqual){ for (i in 1:n) { data <- unlist(datas[[i]]) data.min <- min(data, na.rm = na.rm) data.max <- max(data, na.rm = na.rm) q1[i] <- quantile(data, 0.25) q2[i] <- quantile(data, 0.5) q3[i] <- quantile(data, 0.75) med[i] <- median(data) iqd <- q3[i] - q1[i] upper[i] <- min(q3[i] + range * iqd, data.max) lower[i] <- max(q1[i] - range * iqd, data.min) est.xlim <- c(min(lower[i], data.min), max(upper[i], data.max)) smout <- do.call("sm.density", c(list(data, xlim = est.xlim), args)) if(plotCentre == "line"){ med.dat <- do.call("sm.density", c(list(data, xlim=est.xlim, eval.points=med[i], display = "none"))) med.dens[i] <- med.dat$estimate } Avg.pos <- mean(smout$eval.points) xt <- diff(smout$eval.points[smout$eval.points1){ warning("wex may not be a vector if areaEqual is TRUE") print("using first element of wex") wex<-wex[i] } wex <-unlist(area_check)/max(unlist(area_check))*wex } for (i in 1:n) { data <- unlist(datas[[i]]) data.min <- min(data, na.rm = na.rm) data.max <- max(data, na.rm = na.rm) q1[i] <- quantile(data, 0.25) q2[i] <- quantile(data, 0.5) q3[i] <- quantile(data, 0.75) med[i] <- median(data) iqd <- q3[i] - q1[i] upper[i] <- min(q3[i] + range * iqd, data.max) lower[i] <- max(q1[i] - range * iqd, data.min) est.xlim <- c(min(lower[i], data.min), max(upper[i], data.max)) smout <- do.call("sm.density", c(list(data, xlim = est.xlim), args)) hscale <- 0.4/max(smout$estimate) * ifelse(length(wex)>1, wex[i], wex) base[[i]] <- smout$eval.points height[[i]] <- smout$estimate * hscale t <- range(base[[i]]) baserange[1] <- min(baserange[1], t[1]) baserange[2] <- max(baserange[2], t[2]) if(plotCentre == "line"){ med.dat <- do.call("sm.density", c(list(data, xlim=est.xlim, eval.points=med[i], display = "none"))) med.dens[i] <- med.dat$estimate *hscale } } if (!add) { xlim <- if (n == 1) at + c(-0.5, 0.5) else range(at) + min(diff(at))/2 * c(-1, 1) if (is.null(ylim)) { ylim <- baserange } } if (is.null(names)) { label <- 1:n } else { label <- names } boxwidth <- 0.05 * ifelse(length(boxwex)>1, boxwex[i], boxwex) if (!add){ plot.new() if(!horizontal){ plot.window(xlim, ylim, log = log, asp = asp, bty = bty, cex = cex, xaxs = xaxs, yaxs = yaxs, lab = lab, mai = mai, mar = mar, mex = mex, mfcol = mfcol, mfrow = mfrow, mfg = mfg, xlog = xlog, ylog = ylog) } else { plot.window(ylim, xlim, log = ifelse(log == "y", "x", ""), asp = asp, bty = bty, cex = cex, xaxs = xaxs, yaxs = yaxs, lab = lab, mai = mai, mar = mar, mex = mex, mfcol = mfcol, mfrow = mfrow, mfg = mfg, xlog = ylog, ylog = xlog) } } panel.first if (!horizontal) { if (!add) { plot.window(xlim, ylim, log = log, asp = asp, bty = bty, cex = cex, xaxs = xaxs, yaxs = yaxs, lab = lab, mai = mai, mar = mar, mex = mex, mfcol = mfcol, mfrow = mfrow, mfg = mfg, xlog = xlog, ylog = ylog) xaxp <- par()$xaxp yaxp <- par()$yaxp if(yaxt !="n"){ if(ylog){ #log_axis_label <- log_axis_label[log_axis >= exp(par("usr")[3])] #log_axis <- log_axis[log_axis >= exp(par("usr")[3])] #log_axis_label <- log_axis_label[log_axis <= exp(par("usr")[4])] #log_axis <- log_axis[log_axis <= exp(par("usr")[4])] Axis(unlist(datas), side = 2, cex.axis = cex.axis, col.axis = col.axis, font.axis = font.axis, mgp = mgp, tck = tck, tcl = tcl, las = las) # xaxp = xaxp, yaxp = yaxp disabled for log if(is.null(cex.names)) cex.names <- cex.axis Axis(1:length(datas), at = at, labels = label, side = 1, cex.axis = cex.names, col.axis = col.axis, font.axis = font.axis, mgp = mgp, tck = tck, tcl = tcl, las = las) # xaxp = xaxp, yaxp = yaxp disabled for log } else { Axis(unlist(datas), side = 2, cex.axis = cex.axis, col.axis = col.axis, font.axis = font.axis, mgp = mgp, yaxp = yaxp, tck = tck, tcl = tcl, las = las) if(is.null(cex.names)) cex.names <- cex.axis Axis(1:length(datas), at = at, labels = label, side = 1, cex.axis = cex.names, col.axis = col.axis, font.axis = font.axis, mgp = mgp, xaxp = xaxp, tck = tck, tcl = tcl, las = las) } } } if (frame.plot) { box(lty = lty, lwd = lwd) } for (i in 1:n) { polygon(c(at[i] - radj*height[[i]], rev(at[i] + ladj*height[[i]])), c(base[[i]], rev(base[[i]])), col = ifelse(length(col)>1, col[i], col), border = ifelse(length(border)>1, border[i], border), lty = lty, lwd = lwd, xpd = xpd, lend = lend, ljoin = ljoin, lmitre = lmitre) if (drawRect) { lines(at[c(i, i)], c(lower[i], upper[i]), lwd = lwd, lty = lty, col = ifelse(length(lineCol)>1, lineCol[i], lineCol), lend = lend, ljoin = ljoin, lmitre = lmitre) rect(at[i] - radj*ifelse(length(boxwidth)>1, boxwidth[i], boxwidth)/2, q1[i], at[i] + ladj*ifelse(length(boxwidth)>1, boxwidth[i], boxwidth)/2, q3[i], col = ifelse(length(rectCol)>1, rectCol[i], rectCol), border = ifelse(length(lineCol)>1, lineCol[i], lineCol), xpd = xpd, lend = lend, ljoin = ljoin, lmitre = lmitre) if(plotCentre == "line"){ lines(x = c(at[i] - radj*med.dens[i], at[i], at[i] + ladj*med.dens[i]), y = rep(med[i],3)) } else { points(at[i], med[i], pch = ifelse(length(pchMed)>1, pchMed[i], pchMed), col = ifelse(length(colMed)>1, colMed[i], colMed), bg = ifelse(length(colMed2)>1, colMed2[i], colMed2), cex = cex, lwd = lwd, lty = lty) } } } } else { if(log == "y" || ylog == TRUE){ log <- "x" xlog <- TRUE ylog <- FALSE } if (!add) { plot.window(ylim, xlim, log = log, asp = asp, bty = bty, cex = cex, xaxs = xaxs, yaxs = yaxs, lab = lab, mai = mai, mar = mar, mex = mex, mfcol = mfcol, mfrow = mfrow, mfg = mfg, xlog = xlog, ylog = ylog) xaxp <- par()$xaxp yaxp <- par()$yaxp if(yaxt !="n"){ if(xlog){ #log_axis_label <- log_axis_label[log_axis >= exp(par("usr")[3])] #log_axis <- log_axis[log_axis >= exp(par("usr")[3])] #log_axis_label <- log_axis_label[log_axis <= exp(par("usr")[4])] #log_axis <- log_axis[log_axis <= exp(par("usr")[4])] Axis(unlist(datas), side = 1, cex.axis = cex.names, col.axis = col.axis, font.axis = font.axis, mgp = mgp, tck = tck, tcl = tcl, las = las) # xaxp = xaxp, yaxp = yaxp disabled for log if(is.null(cex.names)) cex.names <- cex.axis Axis(1:length(datas), at = at, labels = label, side = 2, cex.axis = cex.axis, col.axis = col.axis, font.axis = font.axis, mgp = mgp, tck = tck, tcl = tcl, las = las) # xaxp = xaxp, yaxp = yaxp disabled for log } else { Axis(unlist(datas), side = 1, cex.axis = cex.names, col.axis = col.axis, font.axis = font.axis, mgp = mgp, xaxp = xaxp, tck = tck, tcl = tcl, las = las) if(is.null(cex.names)) cex.names <- cex.axis Axis(1:length(datas), at = at, labels = label, side = 2, cex.axis = cex.axis, col.axis = col.axis, font.axis = font.axis, mgp = mgp, yaxp = yaxp, tck = tck, tcl = tcl, las = las) } } } if (frame.plot) { box(lty = lty, lwd = lwd) } for (i in 1:n) { polygon(c(base[[i]], rev(base[[i]])), c(at[i] - radj*height[[i]], rev(at[i] + ladj*height[[i]])), col = ifelse(length(col)>1, col[i], col), border = ifelse(length(border)>1, border[i], border), lty = lty, lwd = lwd, xpd = xpd, lend = lend, ljoin = ljoin, lmitre = lmitre) if (drawRect) { lines(c(lower[i], upper[i]), at[c(i, i)], lwd = lwd, lty = lty, col = ifelse(length(lineCol)>1, lineCol[i], lineCol), lend = lend, ljoin = ljoin, lmitre = lmitre) rect(q1[i], at[i] - radj*ifelse(length(boxwidth)>1, boxwidth[i], boxwidth)/2, q3[i], at[i] + ladj*ifelse(length(boxwidth)>1, boxwidth[i], boxwidth)/2, col = ifelse(length(rectCol)>1, rectCol[i], rectCol), border = ifelse(length(lineCol)>1, lineCol[i], lineCol), xpd = xpd, lend = lend, ljoin = ljoin, lmitre = lmitre) if(plotCentre == "line"){ lines(y = c(at[i] - radj*med.dens[i], at[i], at[i] + ladj*med.dens[i]), x = rep(med[i],3)) } else { points(med[i], at[i], pch = ifelse(length(pchMed)>1, pchMed[i], pchMed), col = ifelse(length(colMed)>1, colMed[i], colMed), , bg = ifelse(length(colMed2)>1, colMed2[i], colMed2), cex = cex, lwd = lwd, lty = lty) } } } } panel.last if (ann) { title(main = main, sub = sub, xlab = xlab, ylab = ylab, line = line, outer = outer, xpd = xpd, cex.main = cex.main, col.main = col.main, font.main = font.main) } invisible(list(upper = upper, lower = lower, median = med, q1 = q1, q3 = q3)) } vioplot/NEWS.md0000644000176200001440000000331613570227632013056 0ustar liggesusers# vioplot 0.3.4 (2019) Bug fixes. - avoids altering base plotting parameters `par()` - resolves issues calling log inputs without an explicit `log` parameter as text # vioplot 0.3.3 (2019) Minor release with improvements to passing parameters. - improved passing of base R plotting parameters - resolves issues with variable names and factor levels in formula inputs # vioplot 0.3.2 (2019) Minor release with improvements to passing parameters. - improved handling for formula input: levels for names and variable names for axes labels - improved passing of graphical parameters to title, and axis - axes for log-scale are automatically generated and horizontal plots are supported Examples for formula input added for convenience (this method is recommended). # vioplot 0.3.1 (2019) Minor release with continuous integration testing, improved vignettes, and License. Compatible with GitHub and CRAN Release. # vioplot 0.3.0 (2018) ## Major changes - formula inputs vioplot is now compatible with all inputs of boxplot or beanplot, including formula inputs (implemented as S3 methods). - plot customisation Various features of violins can be tweaked with plotting parameters, such as colours and shapes of aspects of the violin. These can be applied to all violins with a single (scalar) input or applied separately to each violin with multiple (vector) inputs - defaults This version is fully compatible with inputs to vioplot 0.2. The only difference in behaviour changing the default colour from a glaring magenta to a monochrome grey (more appropriate in a wider range of professional settings). Code written for previous versions should run without breaking or changes in behaviour apart from the default colour. vioplot/MD50000644000176200001440000000573113570256242012272 0ustar liggesusersdabb76aae9f80c4d7758af75730d65a2 *DESCRIPTION b0353042d8325f070abcc2c7300342b8 *LICENSE c420bcce4d184606b2574c2cf3bd3493 *NAMESPACE caa5aaeae25a2b9d79456f8374ea9037 *NEWS.md 0ae71dc06a63bf28adc8102506a72b34 *R/vioplot.R 684f57e60a0be2822d12b4aaf66dc68e *build/vignette.rds cdb1150571725f6e801a839fea1e11d6 *inst/CITATION 203b242b4a9521f975c30c735a0fca45 *inst/COPYRIGHT b3acfff1e90c94b7f89b139ad723cce9 *inst/doc/violin_area.R 278eab2d23325e33e86e7e76dc0c1e90 *inst/doc/violin_area.Rmd a421703e9487054caebe0c75b211a425 *inst/doc/violin_area.html a6c01ad2c1eeb46ccdb9e99a4c7cc52a *inst/doc/violin_customisation.R 61bbd69de37fa4eadb80ecb65e92ebb1 *inst/doc/violin_customisation.Rmd d178ed3ac6f05b7261097d6d1c8d07ce *inst/doc/violin_customisation.html 9b6cefdf921ecd5baf9afbdf43756684 *inst/doc/violin_formulae.R d3ee832b7905a0b7346ad1041e85dfdb *inst/doc/violin_formulae.Rmd 754a40b87d4f1d1288ef191229196817 *inst/doc/violin_formulae.html d2546bc8bd6002a3e25c5ac5968e2e47 *inst/doc/violin_split.R b0809fb61455164f6c7f029a492224fe *inst/doc/violin_split.Rmd 27b4fdaf60ad23fe5cc5c1fd1673b971 *inst/doc/violin_split.html 9f7b64627cf6e2d012c12c8dc7609b30 *inst/doc/violin_ylog.R a41c73ae1df957ee84c4ef8b91e2b36a *inst/doc/violin_ylog.Rmd 144ed4ff82c52429d597c2eec6f46d9a *inst/doc/violin_ylog.html cb60cedd6a5745585f2e0cd54ce0673d *man/vioplot.Rd faccc5d00425006d9beb9babf4752e44 *tests/testthat.R 2f0339e7adda457a1652ebdfb28c2fda *tests/testthat/Rplots.pdf b3e870b5983833f905cb9b0a73520364 *tests/testthat/test_violin_area.R 737539ba9e124f0e0afe268f2981fe89 *tests/testthat/test_violin_customisation.R 32cbdc763f82e46543e055986e6ef0ae *tests/testthat/test_violin_formula.R 85993975a25f4baab807622ba6846ab0 *tests/testthat/test_violin_median.R 9078f2684fba82c384ca17dfa8d38d14 *tests/testthat/test_violin_na_handle.R 70f97529f03d7ffc9e9394752077783e *tests/testthat/test_violin_names.R a38e20901a1dba8f1721f19a4f7e7f9f *tests/testthat/test_violin_side.R f6c59f7fedeed3f7a4df9f3ab8f41eac *tests/testthat/test_violin_unequal_groups.R 13d4f0321b88b6d092ab285ec3e0bf36 *tests/testthat/test_ylog.R f534a569ab6e49235d90a12ff588157e *vignettes/backup/violin_area.Rmd ed82e28a7e639a71348d27caf368d27b *vignettes/backup/violin_area.html 214df39d790c0b9b7fe85e658b261a34 *vignettes/backup/violin_customisation.Rmd f7440770801b4ebb6ac7626e818acc12 *vignettes/backup/violin_customisation.html c4232529d703937acda2edbca88b77ea *vignettes/backup/violin_formulae.html 13f450a14224e623ca331c75bd1edabc *vignettes/backup/violin_split.Rmd 41127ffeefdeb4fadc1c0d9029d14052 *vignettes/backup/violin_split.html 8944fe4605b90795412173ef430e957a *vignettes/backup/violin_ylog.Rmd ad4c189d29867f0a5c820e708f2e0e90 *vignettes/backup/violin_ylog.html 278eab2d23325e33e86e7e76dc0c1e90 *vignettes/violin_area.Rmd 61bbd69de37fa4eadb80ecb65e92ebb1 *vignettes/violin_customisation.Rmd d3ee832b7905a0b7346ad1041e85dfdb *vignettes/violin_formulae.Rmd b0809fb61455164f6c7f029a492224fe *vignettes/violin_split.Rmd a41c73ae1df957ee84c4ef8b91e2b36a *vignettes/violin_ylog.Rmd vioplot/inst/0000755000176200001440000000000013570230421012720 5ustar liggesusersvioplot/inst/doc/0000755000176200001440000000000013570230421013465 5ustar liggesusersvioplot/inst/doc/violin_area.R0000644000176200001440000001243213570230414016104 0ustar liggesusers## ----------------------------------------------------------------------------- library("vioplot") ## ---- message=FALSE----------------------------------------------------------- data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) ## ---- echo=FALSE, message=FALSE----------------------------------------------- par(mar=rep(1,4)) ## ----------------------------------------------------------------------------- par(mfrow=c(3, 1)) par(mar=rep(2, 4)) plot(density(iris$Sepal.Length[iris$Species=="setosa"]), main="Sepal Length: setosa", col="green") plot(density(iris$Sepal.Length[iris$Species=="versicolor"]), main="Sepal Length: versicolor", col="blue") plot(density(iris$Sepal.Length[iris$Species=="virginica"]), main="Sepal Length: virginica", col="palevioletred4") par(mfrow=c(1, 1)) ## ---- echo=FALSE, message=FALSE----------------------------------------------- par(mar=c(5, 4, 4, 2) + 0.1) ## ---- echo=FALSE, message=FALSE----------------------------------------------- par(mar=rep(2,4)) ## ----------------------------------------------------------------------------- par(mfrow=c(3, 1)) par(mar=rep(2, 4)) xaxis <- c(3, 9) yaxis <- c(0, 1.25) plot(density(iris$Sepal.Length[iris$Species=="setosa"]), main="Sepal Length: setosa", col="green", xlim=xaxis, ylim=yaxis) plot(density(iris$Sepal.Length[iris$Species=="versicolor"]), main="Sepal Length: versicolor", col="blue", xlim=xaxis, ylim=yaxis) plot(density(iris$Sepal.Length[iris$Species=="virginica"]), main="Sepal Length: virginica", col="palevioletred4", xlim=xaxis, ylim=yaxis) par(mfrow=c(1, 1)) ## ---- echo=FALSE, message=FALSE----------------------------------------------- par(mar=c(5, 4, 4, 2) + 0.1) ## ----------------------------------------------------------------------------- par(mfrow=c(1, 1)) xaxis <- c(3, 9) yaxis <- c(0, 1.25) plot(density(iris$Sepal.Length[iris$Species=="setosa"]), main="Sepal Length", col="green", xlim=xaxis, ylim=yaxis) lines(density(iris$Sepal.Length[iris$Species=="versicolor"]), col="blue") lines(density(iris$Sepal.Length[iris$Species=="virginica"]), col="palevioletred4") legend("topright", fill=c("green", "blue", "palevioletred4"), legend=levels(iris$Species), cex=0.5) ## ----------------------------------------------------------------------------- vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", areaEqual = T) ## ---- echo=FALSE, message=FALSE----------------------------------------------- par(mar=rep(2, 4)) ## ----------------------------------------------------------------------------- par(mfrow=c(2,1)) par(mar=rep(2, 4)) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Width)", areaEqual = F) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T) par(mfrow=c(1,1)) ## ---- echo=FALSE, message=FALSE----------------------------------------------- par(mar=c(5, 4, 4, 2) + 0.1) ## ----------------------------------------------------------------------------- vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T, col=c("lightgreen", "lightblue", "palevioletred"), rectCol=c("green", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), border=c("darkolivegreen4", "royalblue4", "violetred4")) ## ----------------------------------------------------------------------------- vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T, col=c("lightgreen", "lightblue", "palevioletred"), rectCol=c("green", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), border=c("darkolivegreen4", "royalblue4", "violetred4"), wex=1.25) ## ----------------------------------------------------------------------------- vioplot(rnorm(200, 3, 0.5), rpois(200, 2.5), rbinom(100, 10, 0.4), rlnorm(200, 0, 0.5), rnbinom(200, 10, 0.9), rlogis(20, 0, 0.5), areaEqual = F, main="Equal Width", xlab="distribution", ylab="data value", names=c("normal", "poisson", "binomial", "log-normal", "neg-binomial", "logistic")) vioplot(rnorm(200, 3, 0.5), rpois(200, 2.5), rbinom(100, 10, 0.4), rlnorm(200, 0, 0.5), rnbinom(200, 10, 0.9), rlogis(20, 0, 0.5), areaEqual = T, main="Equal Area", xlab="distribution", ylab="data value", names=c("normal", "poisson", "binomial", "log-normal", "neg-binomial", "logistic")) vioplot/inst/doc/violin_formulae.R0000644000176200001440000000530213570230417017007 0ustar liggesusers## ----------------------------------------------------------------------------- library("vioplot") ## ---- message=FALSE, eval=FALSE----------------------------------------------- # data(iris) # boxplot(Sepal.Length~Species, data = iris) ## ---- message=FALSE, echo=FALSE----------------------------------------------- data(iris) boxplot(Sepal.Length~Species, data = iris, main = "Sepal Length") ## ---- message=FALSE, eval=FALSE----------------------------------------------- # devtools::install_version("vioplot", version = "0.2") # library("vioplot") # vioplot(Sepal.Length~Species, data = iris) ## ---- message=FALSE, eval=FALSE----------------------------------------------- # vioplot(Sepal.Length~Species, data = iris) ## ---- message=FALSE, echo=FALSE----------------------------------------------- vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col="magenta") ## ----------------------------------------------------------------------------- vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length") ## ----------------------------------------------------------------------------- vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col="lightblue") ## ----------------------------------------------------------------------------- vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col=c("lightgreen", "lightblue", "palevioletred")) legend("topleft", legend=c("setosa", "versicolor", "virginica"), fill=c("lightgreen", "lightblue", "palevioletred"), cex = 0.5) ## ----------------------------------------------------------------------------- vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col="lightblue", border="royalblue") ## ----------------------------------------------------------------------------- vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", rectCol="palevioletred", lineCol="violetred") ## ----------------------------------------------------------------------------- vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", colMed="violet") ## ----------------------------------------------------------------------------- vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col="lightblue", border="royalblue", rectCol="palevioletred", lineCol="violetred", colMed="violet") ## ----------------------------------------------------------------------------- vioplot(Sepal.Length~Species, data = iris, main="Sepal Length", col=c("lightgreen", "lightblue", "palevioletred"), border=c("darkolivegreen4", "royalblue4", "violetred4"), rectCol=c("forestgreen", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), colMed=c("green", "cyan", "magenta"), pchMed=c(15, 17, 19)) vioplot/inst/doc/violin_split.R0000644000176200001440000001003513570230420016321 0ustar liggesusers## ---- fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'---- library("vioplot") ## ---- message=FALSE----------------------------------------------------------- data(iris) summary(iris$Sepal.Width) table(iris$Sepal.Width > mean(iris$Sepal.Width)) iris_large <- iris[iris$Sepal.Width > mean(iris$Sepal.Width), ] iris_small <- iris[iris$Sepal.Width <= mean(iris$Sepal.Width), ] ## ---- fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'---- boxplot(Sepal.Length~Species, data=iris, col="grey") ## ---- fig.align = 'center', fig.height = 6, fig.width = 6, fig.keep = 'last'---- { par(mfrow=c(2,1)) boxplot(Sepal.Length~Species, data=iris_small, col = "lightblue") boxplot(Sepal.Length~Species, data=iris_large, col = "palevioletred") par(mfrow=c(1,1)) } ## ---- fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'---- vioplot(Sepal.Length~Species, data=iris) ## ---- fig.align = 'center', fig.height = 6, fig.width = 6, fig.keep = 'last'---- { par(mfrow=c(2,1)) vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "line") vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "line") par(mfrow=c(1,1)) } ## ---- fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'---- vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "line", side = "right") vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "line", side = "left", add = T) title(xlab = "Species", ylab = "Sepal Length") legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width") ## ---- fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'---- vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "point", side = "right", pchMed = 21, colMed = "palevioletred4", colMed2 = "palevioletred2") vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "point", side = "left", pchMed = 21, colMed = "lightblue4", colMed2 = "lightblue2", add = T) title(xlab = "Species", ylab = "Sepal Length") legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width") ## ---- fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'---- vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "point", side = "right", pchMed = 21, colMed = "palevioletred4", colMed2 = "palevioletred2") vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "point", side = "left", pchMed = 21, colMed = "lightblue4", colMed2 = "lightblue2", add = T) points(1:length(levels(iris$Species)), as.numeric(sapply(levels(iris$Species), function(species) median(iris_large[grep(species, iris_large$Species),]$Sepal.Length))), pch = 21, col = "palevioletred4", bg = "palevioletred2") title(xlab = "Species", ylab = "Sepal Length") legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width") ## ---- fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'---- vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "line", side = "right", pchMed = 21, colMed = "palevioletred4", colMed2 = "palevioletred2") vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "line", side = "left", pchMed = 21, colMed = "lightblue4", colMed2 = "lightblue2", add = T) points(1:length(levels(iris$Species)), as.numeric(sapply(levels(iris$Species), function(species) median(iris_large[grep(species, iris_large$Species),]$Sepal.Length))), pch = 21, col = "palevioletred4", bg = "palevioletred2") points(1:length(levels(iris$Species)), as.numeric(sapply(levels(iris$Species), function(species) median(iris_small[grep(species, iris_small$Species),]$Sepal.Length))), pch = 21, col = "lightblue4", bg = "lightblue2") title(xlab = "Species", ylab = "Sepal Length") legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width") vioplot/inst/doc/violin_split.Rmd0000755000176200001440000001374613507766533016704 0ustar liggesusers--- title: "Split Violin Plots" author: "Tom Kelly" date: "`r Sys.Date()`" output: rmarkdown::html_vignette fig_width: 6 fig_height: 3 fig_align: 'center' fig_keep: 'last' vignette: > %\VignetteIndexEntry{vioplot: Split Violin Plots} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ##Violin Plots Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits: - Greater flexibility for plotting variation than boxplots - More familiarity to boxplot users than density plots - Easier to directly compare data types than existing plots As shown below for the `iris` dataset, violin plots show distribution information that the boxplot is unable to. ###General Set up ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} library("vioplot") ``` We set up the data with two categories (Sepal Width) as follows: ```{r, message=FALSE} data(iris) summary(iris$Sepal.Width) table(iris$Sepal.Width > mean(iris$Sepal.Width)) iris_large <- iris[iris$Sepal.Width > mean(iris$Sepal.Width), ] iris_small <- iris[iris$Sepal.Width <= mean(iris$Sepal.Width), ] ``` ###Boxplots First we plot Sepal Length on its own: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} boxplot(Sepal.Length~Species, data=iris, col="grey") ``` An indirect comparison can be achieved with par: ```{r, fig.align = 'center', fig.height = 6, fig.width = 6, fig.keep = 'last'} { par(mfrow=c(2,1)) boxplot(Sepal.Length~Species, data=iris_small, col = "lightblue") boxplot(Sepal.Length~Species, data=iris_large, col = "palevioletred") par(mfrow=c(1,1)) } ``` ### Violin Plots First we plot Sepal Length on its own: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} vioplot(Sepal.Length~Species, data=iris) ``` An indirect comparison can be achieved with par: ```{r, fig.align = 'center', fig.height = 6, fig.width = 6, fig.keep = 'last'} { par(mfrow=c(2,1)) vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "line") vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "line") par(mfrow=c(1,1)) } ``` ### Split Violin Plots A more direct comparision can be made with the `side` argument and `add = TRUE` on the second plot: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "line", side = "right") vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "line", side = "left", add = T) title(xlab = "Species", ylab = "Sepal Length") legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width") ``` ### median The line median option is more suitable for side by side comparisions but the point option is still available also: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "point", side = "right", pchMed = 21, colMed = "palevioletred4", colMed2 = "palevioletred2") vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "point", side = "left", pchMed = 21, colMed = "lightblue4", colMed2 = "lightblue2", add = T) title(xlab = "Species", ylab = "Sepal Length") legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width") ``` It may be necessary to include a `points` command to fix the median being overwritten by the following plots: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "point", side = "right", pchMed = 21, colMed = "palevioletred4", colMed2 = "palevioletred2") vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "point", side = "left", pchMed = 21, colMed = "lightblue4", colMed2 = "lightblue2", add = T) points(1:length(levels(iris$Species)), as.numeric(sapply(levels(iris$Species), function(species) median(iris_large[grep(species, iris_large$Species),]$Sepal.Length))), pch = 21, col = "palevioletred4", bg = "palevioletred2") title(xlab = "Species", ylab = "Sepal Length") legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width") ``` Similarly points could be added where a line has been used previously: ```{r, fig.align = 'center', fig.height = 3, fig.width = 6, fig.keep = 'last'} vioplot(Sepal.Length~Species, data=iris_large, col = "palevioletred", plotCentre = "line", side = "right", pchMed = 21, colMed = "palevioletred4", colMed2 = "palevioletred2") vioplot(Sepal.Length~Species, data=iris_small, col = "lightblue", plotCentre = "line", side = "left", pchMed = 21, colMed = "lightblue4", colMed2 = "lightblue2", add = T) points(1:length(levels(iris$Species)), as.numeric(sapply(levels(iris$Species), function(species) median(iris_large[grep(species, iris_large$Species),]$Sepal.Length))), pch = 21, col = "palevioletred4", bg = "palevioletred2") points(1:length(levels(iris$Species)), as.numeric(sapply(levels(iris$Species), function(species) median(iris_small[grep(species, iris_small$Species),]$Sepal.Length))), pch = 21, col = "lightblue4", bg = "lightblue2") title(xlab = "Species", ylab = "Sepal Length") legend("topleft", fill = c("lightblue", "palevioletred"), legend = c("small", "large"), title = "Sepal Width") ``` Here it is aesthetically pleasing and intuitive to interpret categorical differences in mean and variation in a continuous variable. #### Sources These extensions to `vioplot` here are based on those provided here: * https://gist.github.com/mbjoseph/5852613 These have previously been discussed on the following sites: * https://mbjoseph.github.io/posts/2018-12-23-split-violin-plots/ * http://tagteam.harvard.edu/hub_feeds/1981/feed_items/209875 * https://www.r-bloggers.com/split-violin-plots/ vioplot/inst/doc/violin_ylog.Rmd0000755000176200001440000001031613507766533016511 0ustar liggesusers--- title: "Controlling y-axis Plotting" author: "Tom Kelly" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{vioplot: Controlling y-axis Plotting} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- While boxplots have become the _de facto_ standard for plotting the distribution of data this is a vast oversimplification and may not show everything needed to evaluate the variation of data. This is particularly important for datasets which do not form a Gaussian "Normal" distribution that most researchers have become accustomed to. While density plots are helpful in this regard, they can be less aesthetically pleasing than boxplots and harder to interpret for those familiar with boxplots. Often the only ways to compare multiple data types with density use slices of the data with faceting the plotting panes or overlaying density curves with colours and a legend. This approach is jarring for new users and leads to cluttered plots difficult to present to a wider audience. ##Violin Plots Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits: - Greater flexibility for plotting variation than boxplots - More familiarity to boxplot users than density plots - Easier to directly compare data types than existing plots As shown below for the `iris` dataset, violin plots show distribution information that the boxplot is unable to. ```{r} library("vioplot") ``` ```{r, message=FALSE} data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) ``` ##Violin y-axis ###Logarithmic scale However the existing violin plot packages (such as \code{\link[vioplot]{vioplot}}) do not support log-scale of the y-axis. This has been amended with the `ylog` argument. ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", ylog = T, ylim=c(log(1), log(10))) ``` This can also be invoked with the `log="y"` argument compatible with `boxplot`: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = T, ylim=c(log(1), log(10))) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = "y", ylim=c(log(1), log(10))) ``` ###custom y-axes The y-axes can also be removed with `yaxt="n"` to enable customised y-axes: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", yaxt="n") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", ylog = T, yaxt="n", ylim=c(log(1), log(10))) ``` Thus custom axes can be added to violin plots. As shown on a linear scale: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", yaxt="n") axis(2, at=1:10, labels=1:10) ``` As well as for on a log scale: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", yaxt="n", log="y", ylim=c(log(4), log(9))) axis(2, at=log(1:10), labels=1:10) ``` vioplot/inst/doc/violin_split.html0000644000176200001440000115005613570230420017075 0ustar liggesusers Split Violin Plots

Split Violin Plots

Tom Kelly

2019-11-29

##Violin Plots

Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits:

  • Greater flexibility for plotting variation than boxplots
  • More familiarity to boxplot users than density plots
  • Easier to directly compare data types than existing plots

As shown below for the iris dataset, violin plots show distribution information that the boxplot is unable to.

###General Set up

We set up the data with two categories (Sepal Width) as follows:

##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   2.000   2.800   3.000   3.057   3.300   4.400
## 
## FALSE  TRUE 
##    83    67

###Boxplots

First we plot Sepal Length on its own:

An indirect comparison can be achieved with par:

median

The line median option is more suitable for side by side comparisions but the point option is still available also:

It may be necessary to include a points command to fix the median being overwritten by the following plots:

Similarly points could be added where a line has been used previously:

Here it is aesthetically pleasing and intuitive to interpret categorical differences in mean and variation in a continuous variable.

Sources

These extensions to vioplot here are based on those provided here:

These have previously been discussed on the following sites:

vioplot/inst/doc/violin_area.html0000644000176200001440000110231413570230415016650 0ustar liggesusers Controlling Violin Plot Area

Controlling Violin Plot Area

Tom Kelly

2019-11-29

While boxplots have become the de facto standard for plotting the distribution of data this is a vast oversimplification and may not show everything needed to evaluate the variation of data. This is particularly important for datasets which do not form a Gaussian “Normal” distribution that most researchers have become accustomed to.

While density plots are helpful in this regard, they can be less aesthetically pleasing than boxplots and harder to interpret for those familiar with boxplots. Often the only ways to compare multiple data types with density use slices of the data with faceting the plotting panes or overlaying density curves with colours and a legend. This approach is jarring for new users and leads to cluttered plots difficult to present to a wider audience.

##Violin Plots

Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits:

  • Greater flexibility for plotting variation than boxplots
  • More familiarity to boxplot users than density plots
  • Easier to directly compare data types than existing plots

As shown below for the iris dataset, violin plots show distribution information that the boxplot is unable to.

## Loading required package: sm
## Package 'sm', version 2.2-5.6: type help(sm) for summary information
## Loading required package: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric

##Violin Plot Area

However there are concerns that existing violin plot packages (such as ) scales the data to the most aesthetically suitable width rather than maintaining proportions comparable across data sets. Consider the differing distributions shown below:

#Comparing datasets

Neither of these plots above show the relative distribtions on the same scale, even if we match the x-axis of a density plot the relative heights are obscured and difficult to compare.

This can somewhat be addressed by overlaying density plots:

This has the benefit of highlighting the different distributions of the data subsets. However, notice here that a figure legend become necessary, plot axis limits need to be defined to display the range of all distribution curves, and the plot quickly becomes cluttered if the number of factors to be compared becomes much larger.

##Area control in Violin plot

Therefore the areaEqual parameter has been added to customise the violin plot to serve a similar purpose:

If we compare this to the original vioplot functionality (defaulting to areaEqual = FALSE) the differences between the two are clear.

Note that areaEqual is considering the full area of the density distribution before removing the outlier tails. We leave it up to the users discretion which they elect to use. The areaEqual functionality is compatible with all of the customisation used in discussed in the main vioplot vignette

The violin width can further be scaled with wex, which maintains the proportions across the datasets if areaEqual = TRUE:

vioplot/inst/doc/violin_area.Rmd0000755000176200001440000001714113507652105016437 0ustar liggesusers--- title: "Controlling Violin Plot Area" author: "Tom Kelly" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{vioplot: Controlling Violin Plot Area} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- While boxplots have become the _de facto_ standard for plotting the distribution of data this is a vast oversimplification and may not show everything needed to evaluate the variation of data. This is particularly important for datasets which do not form a Gaussian "Normal" distribution that most researchers have become accustomed to. While density plots are helpful in this regard, they can be less aesthetically pleasing than boxplots and harder to interpret for those familiar with boxplots. Often the only ways to compare multiple data types with density use slices of the data with faceting the plotting panes or overlaying density curves with colours and a legend. This approach is jarring for new users and leads to cluttered plots difficult to present to a wider audience. ##Violin Plots Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits: - Greater flexibility for plotting variation than boxplots - More familiarity to boxplot users than density plots - Easier to directly compare data types than existing plots As shown below for the `iris` dataset, violin plots show distribution information that the boxplot is unable to. ```{r} library("vioplot") ``` ```{r, message=FALSE} data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) ``` ##Violin Plot Area However there are concerns that existing violin plot packages (such as \code{\link[vioplot]{vioplot}}) scales the data to the most aesthetically suitable width rather than maintaining proportions comparable across data sets. Consider the differing distributions shown below: ```{r, echo=FALSE, message=FALSE} par(mar=rep(1,4)) ``` ```{r} par(mfrow=c(3, 1)) par(mar=rep(2, 4)) plot(density(iris$Sepal.Length[iris$Species=="setosa"]), main="Sepal Length: setosa", col="green") plot(density(iris$Sepal.Length[iris$Species=="versicolor"]), main="Sepal Length: versicolor", col="blue") plot(density(iris$Sepal.Length[iris$Species=="virginica"]), main="Sepal Length: virginica", col="palevioletred4") par(mfrow=c(1, 1)) ``` ```{r, echo=FALSE, message=FALSE} par(mar=c(5, 4, 4, 2) + 0.1) ``` #Comparing datasets Neither of these plots above show the relative distribtions on the same scale, even if we match the x-axis of a density plot the relative heights are obscured and difficult to compare. ```{r, echo=FALSE, message=FALSE} par(mar=rep(2,4)) ``` ```{r} par(mfrow=c(3, 1)) par(mar=rep(2, 4)) xaxis <- c(3, 9) yaxis <- c(0, 1.25) plot(density(iris$Sepal.Length[iris$Species=="setosa"]), main="Sepal Length: setosa", col="green", xlim=xaxis, ylim=yaxis) plot(density(iris$Sepal.Length[iris$Species=="versicolor"]), main="Sepal Length: versicolor", col="blue", xlim=xaxis, ylim=yaxis) plot(density(iris$Sepal.Length[iris$Species=="virginica"]), main="Sepal Length: virginica", col="palevioletred4", xlim=xaxis, ylim=yaxis) par(mfrow=c(1, 1)) ``` ```{r, echo=FALSE, message=FALSE} par(mar=c(5, 4, 4, 2) + 0.1) ``` This can somewhat be addressed by overlaying density plots: ```{r} par(mfrow=c(1, 1)) xaxis <- c(3, 9) yaxis <- c(0, 1.25) plot(density(iris$Sepal.Length[iris$Species=="setosa"]), main="Sepal Length", col="green", xlim=xaxis, ylim=yaxis) lines(density(iris$Sepal.Length[iris$Species=="versicolor"]), col="blue") lines(density(iris$Sepal.Length[iris$Species=="virginica"]), col="palevioletred4") legend("topright", fill=c("green", "blue", "palevioletred4"), legend=levels(iris$Species), cex=0.5) ``` This has the benefit of highlighting the different distributions of the data subsets. However, notice here that a figure legend become necessary, plot axis limits need to be defined to display the range of all distribution curves, and the plot quickly becomes cluttered if the number of factors to be compared becomes much larger. ##Area control in Violin plot Therefore the `areaEqual` parameter has been added to customise the violin plot to serve a similar purpose: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", areaEqual = T) ``` If we compare this to the original vioplot functionality (defaulting to `areaEqual = FALSE`) the differences between the two are clear. ```{r, echo=FALSE, message=FALSE} par(mar=rep(2, 4)) ``` ```{r} par(mfrow=c(2,1)) par(mar=rep(2, 4)) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Width)", areaEqual = F) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T) par(mfrow=c(1,1)) ``` ```{r, echo=FALSE, message=FALSE} par(mar=c(5, 4, 4, 2) + 0.1) ``` Note that `areaEqual` is considering the full area of the density distribution before removing the outlier tails. We leave it up to the users discretion which they elect to use. The `areaEqual` functionality is compatible with all of the customisation used in discussed in [the main vioplot vignette](violin_customisation.html) ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T, col=c("lightgreen", "lightblue", "palevioletred"), rectCol=c("green", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), border=c("darkolivegreen4", "royalblue4", "violetred4")) ``` The violin width can further be scaled with `wex`, which maintains the proportions across the datasets if `areaEqual = TRUE`: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T, col=c("lightgreen", "lightblue", "palevioletred"), rectCol=c("green", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), border=c("darkolivegreen4", "royalblue4", "violetred4"), wex=1.25) ``` ## Comparing distributions Notice the utility of `areaEqual` for cases where different datasets have different underlying distributions: ```{r} vioplot(rnorm(200, 3, 0.5), rpois(200, 2.5), rbinom(100, 10, 0.4), rlnorm(200, 0, 0.5), rnbinom(200, 10, 0.9), rlogis(20, 0, 0.5), areaEqual = F, main="Equal Width", xlab="distribution", ylab="data value", names=c("normal", "poisson", "binomial", "log-normal", "neg-binomial", "logistic")) vioplot(rnorm(200, 3, 0.5), rpois(200, 2.5), rbinom(100, 10, 0.4), rlnorm(200, 0, 0.5), rnbinom(200, 10, 0.9), rlogis(20, 0, 0.5), areaEqual = T, main="Equal Area", xlab="distribution", ylab="data value", names=c("normal", "poisson", "binomial", "log-normal", "neg-binomial", "logistic")) ``` vioplot/inst/doc/violin_formulae.html0000644000176200001440000103414613570230417017563 0ustar liggesusers Customising Violin Plots with Formula Input

Customising Violin Plots with Formula Input

Tom Kelly

2019-11-29

Since boxplots have become the de facto standard for plotting the distribution of data most users are familiar with these and the formula input for dataframes. However this input is not available in the standard vioplot package. Thus it has been restored here for enhanced backwards compatibility with boxplot.

As shown below for the iris dataset, violin plots show distribution information taking formula input that boxplot implements but vioplot is unable to. This demonstrates the customisation demonstrated in the main vioplot vignette using vioplot syntax with the formula method commonly used for boxplot, t.test, and lm.

Whereas performing the same function does not work with vioplot (0.2).

Error in min(data) : invalid 'type' (language) of argument

Plot Defaults

Another concern we see here is that the vioplot defaults are not aesthetically pleasing, with a rather glaring colour scheme unsuitable for professional or academic usage. Thus the plot default colours have been changed as shown here:

Plot colours: Violin Fill

Plot colours can be further customised as with the original vioplot package using the col argument:

Plot colours: Violin Lines and Boxplot

Colours can also be customised for the violin fill and border separately using the col and border arguments:

Similarly, the arguments lineCol and rectCol specify the colours of the boxplot outline and rectangle fill. For simplicity the box and whiskers of the boxplot will always have the same colour.

The same applies to the colour of the median point with colMed:

### Combined customisation

These can be customised colours can be combined:

vioplot/inst/doc/violin_ylog.html0000644000176200001440000041600413570230421016712 0ustar liggesusers Controlling y-axis Plotting

Controlling y-axis Plotting

Tom Kelly

2019-11-29

While boxplots have become the de facto standard for plotting the distribution of data this is a vast oversimplification and may not show everything needed to evaluate the variation of data. This is particularly important for datasets which do not form a Gaussian “Normal” distribution that most researchers have become accustomed to.

While density plots are helpful in this regard, they can be less aesthetically pleasing than boxplots and harder to interpret for those familiar with boxplots. Often the only ways to compare multiple data types with density use slices of the data with faceting the plotting panes or overlaying density curves with colours and a legend. This approach is jarring for new users and leads to cluttered plots difficult to present to a wider audience.

##Violin Plots

Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits:

  • Greater flexibility for plotting variation than boxplots
  • More familiarity to boxplot users than density plots
  • Easier to directly compare data types than existing plots

As shown below for the iris dataset, violin plots show distribution information that the boxplot is unable to.

##Violin y-axis

###Logarithmic scale

However the existing violin plot packages (such as ) do not support log-scale of the y-axis. This has been amended with the ylog argument.

## Warning in plot.window(xlim, ylim, log = log, asp = asp, bty = bty, cex = cex, :
## nonfinite axis limits [GScale(-inf,0.362216,2, .); log=1]

## Warning in plot.window(xlim, ylim, log = log, asp = asp, bty = bty, cex = cex, :
## nonfinite axis limits [GScale(-inf,0.362216,2, .); log=1]

This can also be invoked with the log="y" argument compatible with boxplot:

## Warning in plot.window(xlim, ylim, log = log, asp = asp, bty = bty, cex = cex, :
## nonfinite axis limits [GScale(-inf,0.362216,2, .); log=1]

## Warning in plot.window(xlim, ylim, log = log, asp = asp, bty = bty, cex = cex, :
## nonfinite axis limits [GScale(-inf,0.362216,2, .); log=1]

## Warning in plot.window(xlim, ylim, log = log, asp = asp, bty = bty, cex = cex, :
## nonfinite axis limits [GScale(-inf,0.362216,2, .); log=1]

## Warning in plot.window(xlim, ylim, log = log, asp = asp, bty = bty, cex = cex, :
## nonfinite axis limits [GScale(-inf,0.362216,2, .); log=1]

###custom y-axes

The y-axes can also be removed with yaxt="n" to enable customised y-axes:

## Warning in plot.window(xlim, ylim, log = log, asp = asp, bty = bty, cex = cex, :
## nonfinite axis limits [GScale(-inf,0.362216,2, .); log=1]

## Warning in plot.window(xlim, ylim, log = log, asp = asp, bty = bty, cex = cex, :
## nonfinite axis limits [GScale(-inf,0.362216,2, .); log=1]

Thus custom axes can be added to violin plots. As shown on a linear scale:

As well as for on a log scale:

vioplot/inst/doc/violin_ylog.R0000644000176200001440000000526313570230421016150 0ustar liggesusers## ----------------------------------------------------------------------------- library("vioplot") ## ---- message=FALSE----------------------------------------------------------- data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) ## ----------------------------------------------------------------------------- vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", ylog = T, ylim=c(log(1), log(10))) ## ----------------------------------------------------------------------------- vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = T, ylim=c(log(1), log(10))) vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", log = "y", ylim=c(log(1), log(10))) ## ----------------------------------------------------------------------------- vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", yaxt="n") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", ylog = T, yaxt="n", ylim=c(log(1), log(10))) ## ----------------------------------------------------------------------------- vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", yaxt="n") axis(2, at=1:10, labels=1:10) ## ----------------------------------------------------------------------------- vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length", yaxt="n", log="y", ylim=c(log(4), log(9))) axis(2, at=log(1:10), labels=1:10) vioplot/inst/doc/violin_customisation.html0000644000176200001440000073150113570230416020647 0ustar liggesusers Customising Violin Plots

Customising Violin Plots

Tom Kelly

2019-11-29

While boxplots have become the de facto standard for plotting the distribution of data this is a vast oversimplification and may not show everything needed to evaluate the variation of data. This is particularly important for datasets which do not form a Gaussian “Normal” distribution that most researchers have become accustomed to.

While density plots are helpful in this regard, they can be less aesthetically pleasing than boxplots and harder to interpret for those familiar with boxplots. Often the only ways to compare multiple data types with density use slices of the data with faceting the plotting panes or overlaying density curves with colours and a legend. This approach is jarring for new users and leads to cluttered plots difficult to present to a wider audience.

Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits:

  • Greater flexibility for plotting variation than boxplots
  • More familiarity to boxplot users than density plots
  • Easier to directly compare data types than existing plots

As shown below for the iris dataset, violin plots show distribution information that the boxplot is unable to.

Plot Defaults

However as we can see here the plot defaults are not aesthetically pleasing, with a rather glaring colour scheme unsuitable for professional or academic usage. Thus the plot default colours have been changed as shown here:

Plot colours: Violin Lines and Boxplot

Colours can also be customised for the violin fill and border separately using the col and border arguments:

Similarly, the arguments lineCol and rectCol specify the colors of the boxplot outline and rectangle fill. For simplicity the box and whiskers of the boxplot will always have the same colour.

The same applies to the colour of the median point with colMed:

### Combined customisation

These can be customised colours can be combined:

Vectorisation

These color and shape settings can also be customised separately for each violin:

This should be sufficient to customise the violin plot but further examples are given in the areaEqual vioplot vignette including how violin plots are useful for comparing variation when data does not follow the same distribution. This document also compares the violin plot with other established methods to plot data variation.

vioplot/inst/doc/violin_formulae.Rmd0000755000176200001440000001011013507766533017341 0ustar liggesusers--- title: "Customising Violin Plots with Formula Input" author: "Tom Kelly" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{vioplot: Customising Violin Plots with Formula Input} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- Since boxplots have become the _de facto_ standard for plotting the distribution of data most users are familiar with these and the formula input for dataframes. However this input is not available in the standard `vioplot` package. Thus it has been restored here for enhanced backwards compatibility with `boxplot`. As shown below for the `iris` dataset, violin plots show distribution information taking formula input that `boxplot` implements but `vioplot` is unable to. This demonstrates the customisation demonstrated in [the main vioplot vignette using vioplot syntax](violin_customisation.html) with the formula method commonly used for `boxplot`, `t.test`, and `lm`. ```{r} library("vioplot") ``` ```{r, message=FALSE, eval=FALSE} data(iris) boxplot(Sepal.Length~Species, data = iris) ``` ```{r, message=FALSE, echo=FALSE} data(iris) boxplot(Sepal.Length~Species, data = iris, main = "Sepal Length") ``` Whereas performing the same function does not work with `vioplot` (0.2). ```{r, message=FALSE, eval=FALSE} devtools::install_version("vioplot", version = "0.2") library("vioplot") vioplot(Sepal.Length~Species, data = iris) ``` ``` Error in min(data) : invalid 'type' (language) of argument ``` ## Plot Defaults ```{r, message=FALSE, eval=FALSE} vioplot(Sepal.Length~Species, data = iris) ``` ```{r, message=FALSE, echo=FALSE} vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col="magenta") ``` Another concern we see here is that the `vioplot` defaults are not aesthetically pleasing, with a rather glaring colour scheme unsuitable for professional or academic usage. Thus the plot default colours have been changed as shown here: ```{r} vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length") ``` ## Plot colours: Violin Fill Plot colours can be further customised as with the original vioplot package using the `col` argument: ```{r} vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col="lightblue") ``` ### Vectorisation However the `vioplot` (0.2) function is unable to colour each violin separately, thus this is enabled with a vectorised `col` in `vioplot` (0.3): ```{r} vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col=c("lightgreen", "lightblue", "palevioletred")) legend("topleft", legend=c("setosa", "versicolor", "virginica"), fill=c("lightgreen", "lightblue", "palevioletred"), cex = 0.5) ``` ## Plot colours: Violin Lines and Boxplot Colours can also be customised for the violin fill and border separately using the `col` and `border` arguments: ```{r} vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col="lightblue", border="royalblue") ``` Similarly, the arguments `lineCol` and `rectCol` specify the colours of the boxplot outline and rectangle fill. For simplicity the box and whiskers of the boxplot will always have the same colour. ```{r} vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", rectCol="palevioletred", lineCol="violetred") ``` The same applies to the colour of the median point with `colMed`: ```{r} vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", colMed="violet") ``` ### Combined customisation These can be customised colours can be combined: ```{r} vioplot(Sepal.Length~Species, data = iris, main = "Sepal Length", col="lightblue", border="royalblue", rectCol="palevioletred", lineCol="violetred", colMed="violet") ``` ### Vectorisation These colour and shape settings can also be customised separately for each violin: ```{r} vioplot(Sepal.Length~Species, data = iris, main="Sepal Length", col=c("lightgreen", "lightblue", "palevioletred"), border=c("darkolivegreen4", "royalblue4", "violetred4"), rectCol=c("forestgreen", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), colMed=c("green", "cyan", "magenta"), pchMed=c(15, 17, 19)) ``` vioplot/inst/doc/violin_customisation.R0000644000176200001440000001014513570230416020076 0ustar liggesusers## ----------------------------------------------------------------------------- library("vioplot") ## ---- message=FALSE, eval=FALSE----------------------------------------------- # data(iris) # boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) # library("vioplot") # vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) ## ---- message=FALSE, echo=FALSE----------------------------------------------- data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="magenta") ## ----------------------------------------------------------------------------- vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length") ## ----------------------------------------------------------------------------- vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue") ## ----------------------------------------------------------------------------- vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col=c("lightgreen", "lightblue", "palevioletred")) legend("topleft", legend=c("setosa", "versicolor", "virginica"), fill=c("lightgreen", "lightblue", "palevioletred"), cex = 0.5) ## ----------------------------------------------------------------------------- vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue", border="royalblue") ## ----------------------------------------------------------------------------- vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", rectCol="palevioletred", lineCol="violetred") ## ----------------------------------------------------------------------------- vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", colMed="violet") ## ----------------------------------------------------------------------------- vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue", border="royalblue", rectCol="palevioletred", lineCol="violetred", colMed="violet") ## ----------------------------------------------------------------------------- vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T, col=c("lightgreen", "lightblue", "palevioletred"), border=c("darkolivegreen4", "royalblue4", "violetred4"), rectCol=c("forestgreen", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), colMed=c("green", "cyan", "magenta"), pchMed=c(15, 17, 19)) vioplot/inst/doc/violin_customisation.Rmd0000755000176200001440000001453313507766533020445 0ustar liggesusers--- title: "Customising Violin Plots" author: "Tom Kelly" date: "`r Sys.Date()`" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{vioplot: Customising Violin Plots} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- While boxplots have become the _de facto_ standard for plotting the distribution of data this is a vast oversimplification and may not show everything needed to evaluate the variation of data. This is particularly important for datasets which do not form a Gaussian "Normal" distribution that most researchers have become accustomed to. While density plots are helpful in this regard, they can be less aesthetically pleasing than boxplots and harder to interpret for those familiar with boxplots. Often the only ways to compare multiple data types with density use slices of the data with faceting the plotting panes or overlaying density curves with colours and a legend. This approach is jarring for new users and leads to cluttered plots difficult to present to a wider audience. Therefore violin plots are a powerful tool to assist researchers to visualise data, particularly in the quality checking and exploratory parts of an analysis. Violin plots have many benefits: - Greater flexibility for plotting variation than boxplots - More familiarity to boxplot users than density plots - Easier to directly compare data types than existing plots As shown below for the `iris` dataset, violin plots show distribution information that the boxplot is unable to. ```{r} library("vioplot") ``` ```{r, message=FALSE, eval=FALSE} data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) library("vioplot") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica")) ``` ```{r, message=FALSE, echo=FALSE} data(iris) boxplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length") vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="magenta") ``` ## Plot Defaults However as we can see here the plot defaults are not aesthetically pleasing, with a rather glaring colour scheme unsuitable for professional or academic usage. Thus the plot default colours have been changed as shown here: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length") ``` ## Plot colours: Violin Fill Plot colours can be further customised as with the original vioplot package using the `col` argument: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue") ``` ### Vectorisation However the `vioplot` (0.2) function is unable to colour each violin separately, thus this is enabled with a vectorised `col` in `vioplot` (0.3): ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col=c("lightgreen", "lightblue", "palevioletred")) legend("topleft", legend=c("setosa", "versicolor", "virginica"), fill=c("lightgreen", "lightblue", "palevioletred"), cex = 0.5) ``` ## Plot colours: Violin Lines and Boxplot Colours can also be customised for the violin fill and border separately using the `col` and `border` arguments: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue", border="royalblue") ``` Similarly, the arguments `lineCol` and `rectCol` specify the colors of the boxplot outline and rectangle fill. For simplicity the box and whiskers of the boxplot will always have the same colour. ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", rectCol="palevioletred", lineCol="violetred") ``` The same applies to the colour of the median point with `colMed`: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", colMed="violet") ``` ### Combined customisation These can be customised colours can be combined: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main = "Sepal Length", col="lightblue", border="royalblue", rectCol="palevioletred", lineCol="violetred", colMed="violet") ``` ### Vectorisation These color and shape settings can also be customised separately for each violin: ```{r} vioplot(iris$Sepal.Length[iris$Species=="setosa"], iris$Sepal.Length[iris$Species=="versicolor"], iris$Sepal.Length[iris$Species=="virginica"], names=c("setosa", "versicolor", "virginica"), main="Sepal Length (Equal Area)", areaEqual = T, col=c("lightgreen", "lightblue", "palevioletred"), border=c("darkolivegreen4", "royalblue4", "violetred4"), rectCol=c("forestgreen", "blue", "palevioletred3"), lineCol=c("darkolivegreen", "royalblue", "violetred4"), colMed=c("green", "cyan", "magenta"), pchMed=c(15, 17, 19)) ``` This should be sufficient to customise the violin plot but further examples are given in [the areaEqual vioplot vignette](violin_area.html) including how violin plots are useful for comparing variation when data does not follow the same distribution. This document also compares the violin plot with other established methods to plot data variation. vioplot/inst/COPYRIGHT0000755000176200001440000000307513303433326014226 0ustar liggesusersCopyright (c) 2004, Daniel Adler All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the University of Goettingen nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. vioplot/inst/CITATION0000755000176200001440000000117713570227610014074 0ustar liggesuserscitHeader("To cite the enhanced vioplot package in publications use:") citEntry(entry = "Manual", title = "vioplot: violin plot", author = personList(as.person("Daniel Adler"),as.person("S. Thomas Kelly")), year = "2019", note = "R package version 0.3.4", url = "https://github.com/TomKellyGenetics/vioplot", textVersion = paste("Daniel Adler and S. Thomas Kelly (2019). vioplot: violin plot. R package version 0.3.4", "https://github.com/TomKellyGenetics/vioplot") ) citFooter(paste("Please also acknowledge the original package: \n citation(", "vioplot", ")", sep="\""))