Visualisation of Likert scale results

July 31, 2016
By

(This article was first published on Rcrastinate, and kindly contributed to R-bloggers)

I wrote a function to visualise results of Likert scale items. Please find the function below the post. Here is an example plot:

The function is called ‘plot.likert’ and takes the following arguments:
– vec: The vector with the raw results
– possible.values: A vector with all the possible values. This is sometimes important if not all possible responses were actually ticked by your participants. Defaults to all values found in vec.
– left: Annotation for the left side of the plot
– right: Annotation for the right side of the plot
– plot.median: Plot the median as a little line at the top? Defaults to FALSE.
– plot.sd: Plot the standard deviation around the mean? Defaults to TRUE.
– include.absolutes: Include the absolute values as small bold black numbers above the plot? Defaults to TRUE.
– include.percentages: Include the percentage values as blue numbers above the plot? Defaults to TRUE.
– own.margins: Override the default margins for the plot. Defaults to c(2,2,3,2).
– othermean: Plot another mean into the visualisation as grey line above the bars. I used this to compare the results to older results for the same questions. Defaults to NULL (no other mean is plotted in this case).
– …: Other parameters might be passed that are used for the first call to plot().
The example call for the plot shown above is:
plot.likert(sample(-2:2, 75, replace = T,
                   prob = c(0, .2, .2, .3, .3)),
            left = “strongly disagree”,
            right = “strongly agree”,
            own.margins = c(2,2,5,2),
            main = “I like this visualisation of Likert scale
                    results.”,
            possible.values = -2:2,
            othermean = 1.09)

NB: I know of all the stuff regarding the calculation of means on Likert scale items. However, it is still done a lot and you can also include the median after all…

Here’s the function:

plot.likert <- function (vec, possible.values = sort(unique(vec)), left = “linker Pol”, right = “rechter Pol”,
                         plot.median = F, plot.sd = T, include.absolutes = T, include.percentages = T, own.margins = c(2, 2, 3, 2),
                         othermean = NULL, …) {
  tab <- table(vec)
  if (length(tab) != length(possible.values)) {
    values.not.in.tab <- possible.values[!(possible.values %in% names(tab))]
    for (val in values.not.in.tab) {
      tab[as.character(val)] <- 0
    }
    tab <- tab[sort(names(tab))]
  }
  prop.tab <- prop.table(tab) * 100
  v.sd <- sd(vec, na.rm = T)
  v.m <- mean(vec, na.rm = T)
  v.med <- median(vec, na.rm = T)
  old.mar <- par(“mar”)
  par(mar = own.margins)
  # Setting-up plot region
  plot(x = c(min(as.numeric(names(tab)), na.rm = T) – 1.1, max(as.numeric(names(tab)), na.rm = T) + 1.1),
       y = c(0, 100), type = “n”, xaxt = “n”, yaxt = “n”,
       xlab = “”, ylab = “”, bty = “n”, …)
  # Bars
  rect(xleft = as.numeric(names(prop.tab)) – .4,
       ybottom = 0,
       xright = as.numeric(names(prop.tab)) + .4,
       ytop = prop.tab,
       border = “#00000000”, col = “#ADD8E6E6”)
  # Lower black line
  lines(x = c(min(as.numeric(names(tab)), na.rm = T) – .6, max(as.numeric(names(tab)), na.rm = T) + .6),
        y = c(0, 0), col = “black”, lwd = 2)
  # Upper black line
  lines(x = c(min(as.numeric(names(tab)), na.rm = T) – .6, max(as.numeric(names(tab)), na.rm = T) + .6),
        y = c(100, 100), col = “black”, lwd = 2)
  # Blue lines
  for (n.i in names(tab)) {
    lines(x = c(n.i, n.i), y = c(0, 100), col = “blue”)
  }
  # Grey rectangles at sides
  rect(xleft = min(as.numeric(names(tab)), na.rm = T) – 1.1,
       ybottom = 0,
       xright = min(as.numeric(names(tab)), na.rm = T) – .6,
       ytop = 100,
       border = “#00000000”, col = “grey”)
  rect(xleft = max(as.numeric(names(tab)), na.rm = T) + .6,
       ybottom = 0,
       xright = max(as.numeric(names(tab)), na.rm = T) + 1.1,
       ytop = 100,
       border = “#00000000”, col = “grey”)
  mtext(names(prop.tab), side = 1, at = names(prop.tab))
  # Percentages and numbers at the top
  if (include.percentages) mtext(paste(round(prop.tab, 0), “%”), side = 3, at = names(prop.tab), line = -.3, col = “blue”)
  if (include.absolutes) mtext(tab, side = 3, at = names(tab), line = .5, cex = .8, font = 2)
  # Mean line
  lines(x = c(v.m, v.m), y = c(95, 85), lwd = 6, col = “blue”)
  # Median line
  if (plot.median) lines(x = c(v.med, v.med), y = c(95, 85), lwd = 4, col = “#00FF00AA”)
  # Other mean line
  if (!is.null(othermean)) lines(x = c(othermean, othermean), y = c(85, 75), lwd = 6, col = “#00000099”)
  # SD lines
  if (plot.sd) { arrows(x0 = c(v.m, v.m), x1 = c(v.m – v.sd, v.m + v.sd), y0 = c(90, 90), y1 = c(90, 90),
                        angle = 90, length = 0, lwd = 1) }
  # Left label
  mtext(left, side = 2, line = -.5)
  # Right label
  mtext(right, side = 4, line = -.5)
  par(mar = old.mar)
}

To leave a comment for the author, please follow the link and comment on their blog: Rcrastinate.

R-bloggers.com offers daily e-mail updates about R news and tutorials on topics such as: Data science, Big Data, R jobs, visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...



If you got this far, why not subscribe for updates from the site? Choose your flavor: e-mail, twitter, RSS, or facebook...

Comments are closed.

Sponsors

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)