Barplot type

Description

Type function for producing barplots. For formulas of type ~ x (without left-hand side) the barplot visualizes the counts (absolute frequencies) of the levels of x. For formulas of type y ~ x the value of y within each level of x is visualized, if necessary aggregated using some function (default: mean).

Usage

type_barplot(
  width = 5/6,
  beside = FALSE,
  center = FALSE,
  offset = NULL,
  FUN = NULL,
  xlevels = NULL,
  xaxlabels = NULL,
  drop.zeros = FALSE
)

Arguments

width numeric, optional vector of bar widths. (The distance between the midpoints of the bars is always 1.)
beside logical. In case of a by grouping variable, should bars be juxtaposed? Default is to use stacked bars instead.
center logical or numeric. In case of stacked barplots (beside = FALSE) should the bars be centered (or all start at zero, default)? If set to TRUE the center is at the mid-point of the middle category (in case of uneven number of categories) or between the two middle categories (in case of an even number). Additionally it is possible to set center = 2 or center = 2.5 to indicate that centering should be after the second category or the mid-way in the third category, respectively.
offset

optional specification for shifting bar baselines, accepting one of two distinct forms. See the Examples for illustrations of both.

  • Positions via an unnamed numeric scalar or vector. Bars start at the offset value(s) rather than zero, matched per x-level after any xlevels reordering (a scalar is applied to all bars). Useful for waterfall charts. The positional form cannot be combined with center.

  • Category via a character vector such as offset = “Unsure”, or a named numeric vector such as offset = c(Unsure = 1.1). The named level(s) of the by grouping are "set aside", i.e. pulled out of the (optionally centered) stack and drawn as standalone bars. This is useful for diverging/Likert plots where a neutral category (e.g. "Unsure") is shown apart from the diverging stack. The category form requires a by grouping and beside = FALSE, but can be combined with center.

FUN a function to compute the summary statistic for y within each group of x in case of using a two-sided formula y ~ x (default: mean).
xlevels a character or numeric vector specifying the ordering of the levels of the x variable (if character) or the corresponding indexes (if numeric) for the plot.
xaxlabels a character vector with the axis labels for the x variable, defaulting to the levels of x.
drop.zeros logical. Should bars with zero height be dropped? If set to FALSE (default) a zero height bar is still drawn for which the border lines will still be visible.

Examples

library("tinyplot")

# Basic examples of frequency tables (without y variable)
tinyplot(~ cyl, data = mtcars, type = "barplot")

tinyplot(~ cyl | vs, data = mtcars, type = "barplot")

tinyplot(~ cyl | vs, data = mtcars, type = "barplot", beside = TRUE)

tinyplot(~ cyl | vs, data = mtcars, type = "barplot", beside = TRUE, fill = 0.2)

# Reorder x variable categories either by their character levels or numeric indexes
tinyplot(~ cyl, data = mtcars, type = "barplot", xlevels = c("8", "6", "4"))

tinyplot(~ cyl, data = mtcars, type = "barplot", xlevels = 3:1)

# Note: Above we used automatic argument passing for `beside`. But this
# wouldn't work for `width`, since it would conflict with the top-level
# `tinyplot(..., width = <width>)` argument. It's safer to pass these args
# through the `type_barplot()` functional equivalent.
tinyplot(
  ~ cyl | vs, data = mtcars, fill = 0.2,
  type = type_barplot(beside = TRUE, drop.zeros = TRUE, width = 0.65)
)

# Example for numeric y aggregated by x (default: FUN = mean) + facets
tinyplot(
  extra ~ ID | group, facet = "by", data = sleep,
  type = "barplot", fill = 0.6,
  theme = "clean2"
)

# Fancy frequency table:
tinyplot(
  Freq ~ Sex | Survived, data = as.data.frame(Titanic),
  facet = ~ Class, facet.args = list(nrow = 1),
  type = "barplot", flip = TRUE, fill = 0.6,
  theme = "clean2"
)

# Centered barplot for conditional proportions of hair color (black/brown vs.
# red/blond) given eye color and sex
hec = as.data.frame(proportions(HairEyeColor, 2:3))
hcols = c("black", "sienna", "indianred", "goldenrod")
tinyplot(
  Freq ~ Eye | Hair, data = hec,
  facet = ~ Sex, facet.args = list(ncol = 1),
  type = "barplot", center = TRUE,
  flip = TRUE, yaxl = "percent",
  theme = list("clean2", palette.qualitative = hcols)
)

# Use cases for the `offset` argument

# 1. Waterfall plot
d = data.frame(item = c("Sales", "Services", "Costs", "Returns", "TOTAL"),
               value = c(100, 40, -80, -10, 50))
d$item = factor(d$item, levels = d$item)
d$offset = c(0, cumsum(d$value[1:3]), 0)
tinyplot(
  value ~ item | I(value < 0), data = d,
  type = type_barplot(offset = d$offset), legend = FALSE
)
tinyplot_add(type = type_vline(4.5), lty = 2)

# 2. Diverging/Likert layout: a character (or named numeric) offset "sets
# aside" the named category, pulling it out of the centered stack and drawing
# it as a standalone bar. Here a neutral "Unsure" response is shown apart from
# the diverging agree/disagree scale.
lik = expand.grid(
  question = c("Pay", "Workload", "Manager", "Culture"),
  response = c("Strong disagree", "Disagree", "Agree", "Strong agree", "Unsure")
)
lik$response = factor(lik$response, levels = unique(lik$response))
lik$share = c( # proportions summing to 1 within each question
  .10, .25, .05, .15,
  .20, .30, .15, .20,
  .35, .20, .40, .30,
  .25, .15, .35, .20,
  .10, .10, .05, .15
)
# diverging palette: reds (disagree) -> blues (agree), grey for "Unsure"
pal = c("#b2182b", "#ef8a62", "#67a9cf", "#2166ac", "grey")
tinyplot(
  share ~ question | response, data = lik,
  type = "barplot", center = TRUE, offset = "Unsure",
  flip = TRUE, xlab = NA, ylab = NA, yaxl = "percent",
  legend = list("top!", title = NULL),
  theme = list("clean2", palette.qualitative = pal),
  main = "Hypothetical Likert example with category offset"
)
tinyplot_add(type = "vline")