Diverging stacked barcharts for Likert, semantic differential, rating scale data, and population pyramids based on mosaic as the plotting style.

Constructs and plots diverging stacked barcharts for Likert, semantic differential, rating scale data, and population pyramids, .based on mosaic as the plotting style.

likertMosaic(x, ...)

## S3 method for class 'formula': likertMosaic(x, data, ReferenceZero = NULL, spacing=NULL, ..., between.y = c(1.2, 0.3))

## S3 method for class 'array': likertMosaic(x, ReferenceZero = NULL, col = NULL, main = NULL, ..., as.percent = FALSE, variable.width = NULL, positive.order = FALSE, Conditions = NULL, x.legend = list(text = list(dimnames(x)[[ndim]]), columns = x.dim[ndim], space = "bottom", size = 2, cex = 0.8, between = 0.6, rect= list(col = col, border = "white")), legend.y = 0.05, spacing = spacing_highlighting, split_vertical = c(TRUE, FALSE), margins = c(3, 2, 4, 22), keep_aspect = FALSE, rot_labels = c(0, 0, 90, 0), just_labels = c("center", "center", "center", "right"), labels = c(TRUE, TRUE, FALSE, TRUE), varnames = FALSE, zero_size = 0, gp = gpar(fill = col.extended, col = 0), colorFunction="diverge_hcl", colorFunctionOption="lighter")

## S3 method for class 'data.frame': likertMosaic(x, ...)

## S3 method for class 'default': likertMosaic(x, ...) ## most likely for a vector

## S3 method for class 'list': likertMosaic(x, ...)

## S3 method for class 'matrix': likertMosaic(x, ..., split_vertical = c(FALSE, TRUE), rot_labels = c(90, 0, 0, 0), just_labels = c("left", "center", "center", "right"), labels = c(TRUE, FALSE))

For the formula method, a model formula. Otherwise, any numeric object stored as a vector, matrix, array, data.frame, table, ftable, structable (as defined in the vcd package), or as a list of named two-dimensional objects.
For the formula method, a data.frame.
Numeric scalar or NULL. The position in the range seq(0, attr(x, "nlevels")+.5, .5) where the reference line at 0 will be placed. attr(x, "nlevels") is the number of columns of the original argument
If FALSE, the default value, the original order of the rows is retained. This is necessary for arrays, because each panel has the same rownames. If TRUE, rows are ordered within each panel with the row whose bar goe
When as.percent==TRUE or as.percent=="noRightAxis", then the values in each row are rescaled to row percents.
When TRUE and as.percent==TRUE, then the area of the bars (percent along the length times the width) is proportional to the counts.
Colors for the bars. With the default value NULL, the colors are chosen from the default diverge_hcl diverging palette. Any color specification that R understands can be used he
colorFunction, colorFunctionOption
See likertColor.
main title for the plot.
Additional arguments, passed to the next method and possibly all the way to strucplot.
Factor used to divide the rows of the plot into sets of rows corresponding to levels of Condition. In the formula method, the conditions are the factors appearing after the | symbol.
vertical spacing between bars. between.y[1] is used between levels of conditioning factors, and between.y[2] is used between bars within the same level of the conditioning factor.
Description of legend using the terminology and conventions of the lattice package.
Adjust vertical location of legend.
spacing, split_vertical, margins, keep_aspect, rot_labels, just_labels, labels
Please see strucplot for details.
varnames, zero_size, gp
Please see strucplot for details.

The counts (or percentages) of respondents on each row who agree with the statement are shown to the right of the zero line; the counts (or percentages) who disagree are shown to the left. The counts (or percentages) for respondents who neither agree nor disagree are split down the middle and are shown in a neutral color. The neutral category is omitted when the scale has an even number of choices. It is difficult to compare lengths without a common baseline. In this situation, we are primarily interested in the total count (or percent) to the right or left of the zero line; the breakdown into strongly or not is of lesser interest so that the primary comparisons do have a common baseline of zero. The rows within each panel are displayed in their original order by default. If the argument positive.order=TRUE is specified, the rows are ordered by the counts (or percentages) who agree.

Diverging stacked barcharts are also called "two-directional stacked barcharts". Some authors use the term "floating barcharts" for vertical diverging stacked barcharts and the term "sliding barcharts" for horizontal diverging stacked barcharts.

All items in a list of named two-dimensional objects must have the same number of columns. If the items have different column names, the column names of the last item in the list will be used in the key. If the dimnames of the matrices are named, the names will be used in the plot. It is possible to produce a likert plot with a list of objects with different numbers of columns, but not with the plot.likert.list method. These must be done manually by using the ResizeEtc function on each of the individual likert plots. The difficulty is that the legend is based on the last item in the list and will have the wrong number of values for some of the panels.

A single data.frame x will be plotted as data.matrix(x); therefore factor columns will be converted to integers and character columns will become NA and will be plotted as if they had value 0. A data.frame with only numeric columns will work in a named list. A data.frame with factors or characters won't work in a named list.

ftable and structable arguments x will be plotted as as.table(x). This changes the display sequence. Therefore the user will probably want to use aperm on the ftable or structable before using plot.likert.


  • Please see strucplot for a description of the returned object.


The functions described here are currently missing the following features:

  1. no axis ticks, number, nor axis label for the x axis
  2. no zero reference line
  3. no right-axis labels for Row Count Totals
  4. no strip.left labels for grouping by Conditions
  5. In Figure 8 and 9 (HH/demo/likertMosaic-paper.r), no control of the thickness of the bars
  6. All bars are horizontal.
  7. No borders on the overall plot nor on the panels in plots with grouping by Conditions
  8. No control ofbetween=list(x=number)
  9. cexfor labeling
  10. border on empty boxes
  11. I am using a lattice legend, not a native strucplot legend


Richard M. Heiberger, Naomi B. Robbins (2014)., "Design of Diverging Stacked Bar Charts for Likert Scales and Other Applications", Journal of Statistical Software, 57(5), 1--32,

Richard Heiberger and Naomi Robbins (2011), "Alternative to Charles Blow's Figure in "Newt's War on Poor Children"", Forbes OnLine, December 20, 2011.

Naomi Robbins (2011), "Visualizing Data: Challenges to Presentation of Quality Graphics---and Solutions", Amstat News, September 2011, 28--30.

Naomi B. Robbins and Richard M. Heiberger (2011). Plotting Likert and Other Rating Scales. In JSM Proceedings, Section on Survey Research Methods. Alexandria, VA: American Statistical Association, 1058--1066.

Luo, Amy and Tim Keyes (2005). "Second Set of Results in from the Career Track Member Survey," Amstat News. Arlington, VA: American Statistical Association.

See Also

likert, mosaic

  • likertMosaic
  • likertMosaic.array
  • likertMosaic.default
  • likertMosaic.formula
  • likertMosaic.list
  • likertMosaic.matrix
## See file HH/demo/likertMosaic-paper.r for a complete set of examples.
  likertMosaic(Question ~ . | Subtable, ProfChal,
               main="Is your job professionally challenging?")
  likertMosaic(Question ~ . | Subtable, ProfChal,
               main="Is your job professionally challenging?", as.percent=TRUE)
  likertMosaic(Question ~ . | Subtable, ProfChal,
               main="Is your job professionally challenging?", as.percent=TRUE,
  likertMosaic(Question ~ . | Subtable, ProfChal,
               main="Is your job professionally challenging?", as.percent=TRUE,

  EmpRows <- ProfChal$Subtable == "Employment sector"
  ProfChal2 <- ProfChal[EmpRows, 1:5]
  rownames(ProfChal2) <- substr(ProfChal[EmpRows, "Question"], 1, 5)

  likertMosaic(ProfChal2, main="Employment")
  likertMosaic(ProfChal2, main="Employment", ReferenceZero=0)
  likertMosaic(ProfChal2, main="Employment", ReferenceZero=3.5)
  likertMosaic(ProfChal2, main="Employment", ReferenceZero=4)
  likertMosaic(ProfChal2, main="Employment", ReferenceZero=6)
  likertMosaic(ProfChal2, main="Employment", positive.order=TRUE)
  likertMosaic(ProfChal2, main="Employment", variable.width=TRUE)

  likertMosaic(~ ., data.frame(ProfChal2), main="Employment", positive.order=TRUE)

  likertMosaic(~ ., data.frame(ProfChal2), main="Employment", variable.width=TRUE)
  likert(~ ., data.frame(ProfChal2), main="Employment", variable.width=TRUE)

  likertMosaic(aperm(SFF8121, c(3,1,2)))
Documentation reproduced from package HH, version 3.0-4, License: GPL (>= 2)

Community examples

Looks like there are no examples yet.