library("tinyplot")
#
## Basic use (raw values)
# (named) atomic vector
tinyplot(c(A = 1, B = 2, C = 3), type = "barplot")
# formula + data.frame method
tinyplot(GNP ~ Year, data = longley, type = "barplot")
tinyplot(demand ~ Time, data = BOD, type = "bar") # "bar" is a shorthand
tinyplot_add(type = "text", pos = 3, xpd = NA) # add y values as text
# reordering (just to demonstrate; these aren't sensible for a time variable)
tinyplot(demand ~ Time, data = BOD, type = "bar", xord = "asc")
jumble = c("7","1","5","2","4","3") # note: Time = 6 is also missing
tinyplot(demand ~ Time, data = BOD, type = "bar", xlevels = jumble) 
# useful top-level args:
# 1) xaxl to format the x labels, e.g. with a dictionary, keyword, or (here:)
# function
# 2) xaxr to rotate long category labels (best used with a dynamic theme)
tinyplot(
demand ~ Time, data = BOD,
type = "bar",
xaxl = function(x) paste("Time =", x),
xaxr = 45,
theme = "broadsheet"
)
#
## Aggregated vs grouped values (multiple ys per x)
# each person receives two drugs
sleep2 = transform(sleep, drug = group) # less misleading name
# default aggregation FUN is mean
tinyplot(
extra ~ ID, data = sleep2,
type = "barplot",
main = "Mean extra sleep from 2 soporific drugs"
)
# switch to diff (answers a more relevant q: who benefits most from drug 2?)
tinyplot(
extra ~ ID, data = sleep2,
type = "barplot", FUN = diff,
main = "Sleep gain (drug 2 vs drug 1)"
)
# we can sort in descending (or ascending) order too
tinyplot(
extra ~ ID, data = sleep2,
type = "barplot", FUN = diff, xord = "desc",
main = "Sleep gain (drug 2 vs drug 1), ordered"
)
# of course, we don't have to aggregate if we specify groups (stacked or non)
tinyplot(extra ~ ID | drug, data = sleep2, type = "barplot", beside = TRUE)
# Aside: We used automatic argument passing for 'xord', `FUN`, etc. above.
# 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(
extra ~ ID | drug, data = sleep2,
type = type_barplot(beside = TRUE, xord = "desc", width = 0.5)
)
#
## matrix method (no formula required)
tinyplot(VADeaths, type = "barplot")
tinyplot(VADeaths, type = "barplot", beside = TRUE)
# etc. see ?tinyplot.matrix
#
## Frequency tables
# No y variable (frequency calculated on the fly)
tinyplot(~ cyl, data = mtcars, type = "barplot")
tinyplot(~ cyl | vs, data = mtcars, type = "barplot")
tinyplot(~ cyl | vs, data = mtcars, type = "barplot", beside = TRUE)
# Fancy frequency table (y = frequency aleady computed)
tinyplot(
Freq ~ Sex | Survived, data = as.data.frame(Titanic),
facet = ~ Class, facet.args = list(nrow = 1),
type = "barplot", beside = TRUE, flip = TRUE,
theme = "clean2"
)
#
## Centering
# Centered barplot for conditional proportions of "dark" (black/brown) vs.
# "fair" (red/blond) hair color, conditional on eye color and sex.
# Aside: use `lighten = FALSE` to avoid lightening the bar fill colors.
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 = type_barplot(center = TRUE, lighten = FALSE),
flip = TRUE, yaxl = "percent",
theme = list("clean2", palette.qualitative = hcols)
)
tinyplot_add(type = "vline", col = "white")
#
## Offset examples
# 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, lighten = FALSE),
legend = FALSE
)
tinyplot_add(type = type_vline(4.5), lty = 2, col = "grey50")
# 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$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 = type_barplot(center = TRUE, offset = "Unsure", lighten = FALSE),
flip = TRUE, xlab = NA, ylab = NA, yaxl = "percent",
legend = list("top!", title = FALSE),
theme = list("clean2", palette.qualitative = pal),
main = "Hypothetical Likert example with category offset"
)
tinyplot_add(type = "vline")
tinyplot_add(type = "vline", v = 1, lty = 2)
#
## Implicit zeros and empty cells (see the section of the same name above)
# No (mt)car has 8 cylinders and a straight engine, so that bar is a count
# of zero and is marked as such (flat, along the baseline)
tinyplot(~ cyl | vs, data = mtcars, type = "barplot", facet = "by")
# But in this example, the aggregating statistic is a mean rather than a
# count. The mean of unobserved combinations (e.g., carb==1 & vs==0) is
# is undefined, so nothing is drawn for the empty cells
tinyplot(
mpg ~ factor(carb), data = mtcars,
type = "barplot",
facet = ~ vs, facet.args = list(ncol = 1)
)
# ... use na.as.zero to override and mark as (implicit) zeros
tinyplot(
mpg ~ factor(carb), data = mtcars,
type = type_barplot(na.as.zero = TRUE),
facet = ~ vs, facet.args = list(ncol = 1)
)