"label"
attribute in columns."label"
attribute in columns.Label attribute automatically detected.
Example dictionary for mtcars
dict <- tibble::tribble(
~column, ~label, ~unit, ~note,
"mpg", "Efficiency", "mi/gal", "Gallons are US gallons",
"cyl", "Number of cylinders", "", "",
"disp", "Engine Displacement", "in^3", "",
"am", "Transmission", "", "0 = automatic, 1 = manual"
)
dict
# A tibble: 4 × 4
column label unit note
<chr> <chr> <chr> <chr>
1 mpg Efficiency "mi/gal" "Gallons are US gallons"
2 cyl Number of cylinders "" ""
3 disp Engine Displacement "in^3" ""
4 am Transmission "" "0 = automatic, 1 = manual"
factor(cyl)
or cyl + 1
do not get automatic labelsattr(data$var, "label")
labs(dictionary)
⏲️ Exercise 1.2.1 & 1.2.2
In R 4.1 the grid package introduced patterns and gradients.
grid::linearGradient()
grid::radialGradient()
grid::pattern()
We allow these as fill
aesthetic in ggplot2.
Patterns can aid in cases of colour vision deficiency.
Simple examples of linear and radial gradients.
Use these gradients by providing them as a list.
Patterns are more complicated. You may need to know a little bit of grid to get these right. Here we’re using a diagonal line as a pattern.
Like gradients, patterns can be given as a list.
To ‘fix’ patterning artefacts, you may need to adjust the strokes in the inner drawing.
Using patterns as a scale.
Ribbon geometries now render a varying fill
aesthetic as a gradient.
Using the gridpattern package to easily generate patterns.
herringbone <- gridpattern::patternFill(
"polygon_tiling",
type = "herringbone",
spacing = 0.2,
units = "cm",
colour = "grey40",
linewidth = 0.3
)
hexagons <- gridpattern::patternFill(
"polygon_tiling",
type = "hexagonal",
spacing = 0.2,
units = "cm",
colour = "grey40",
linewidth = 0.3
)
waves <- gridpattern::patternFill(
"wave",
spacing = 0.2,
units = "cm",
colour = "grey40",
linewidth = 0.3
)
Using the gridpattern package to easily generate patterns.
Parametrised patterns with the ggpattern package.
Emoji isotype plot using text patterns.
# Helper function
width <- unit(20, "pt")
patternise_text <- function(text) {
lapply(text, function(string) {
grob <- textGrob(string, x = 0, hjust = 0, gp = gpar(fontsize = 18))
pattern(
grob,
x = 0, hjust = 0,
width = width,
extend = "repeat",
# Center text per bar using height/group
height = unit(1, "npc"),
group = FALSE
)
})
}
# Stats for the Netherlands
df <- data.frame(
animal = c("chickens", "pigs", "cows", "sheep", "goats", "humans"),
amount = c(99900000, 11400000, 3800000, 850000, 480000, 17990000)
)
ggplot(df, aes(amount, animal, fill = animal)) +
geom_col() +
scale_fill_manual(
values = patternise_text(c(
"chickens" = "🐓",
"pigs" = "🐖",
"cows" = "🐄",
"sheep" = "🐑",
"goats" = "🐐",
"humans" = "🧍"
))
) +
scale_x_continuous(
labels = scales::label_number(scale = 1e-6, suffix = "M")
) +
theme(
legend.key.width = width,
legend.key.height = unit(18, "pt") # see fontsize in pattern
)
For most control over patterns.
grid::pattern()
, grid::linearGradient()
, grid::radialGradient()
.
For great selection of preformatted patterns.
gridpattern::patternFill()
For mapping data to patterns.
pattern_density
)ggpattern::geom_boxplot_pattern()
)ggpattern::scale_pattern_density_continuous()
)⏲️ Exercise 1.2.3 & 1.2.4
With regards to evaluation, there are three stages:
Data available from the start, when mapped from data columns.
Unmapped aesthetics like geom_bar(fill = "red")
are not direct input.
Data columns that are not mapped are not input.
In addition to aesthetics, computed variables become available.
These are listed in a documentation section in e.g. ?stat_density
.
Sometimes, these are used by default and can be recognised by the use of after_stat()
.
You can use after_stat()
yourself to redirect or modify stat outputs.
You may have run into a histogram/density misalignment problem.
This can be fixed by using the density
computed variable in the histogram.
Or scaling the count
computed variable in the density.
At this stage in the plot, the variables are mapped by the scales.
It means that the hex codes from colour scales are available, the sizes and shapes of points and other variables mapped by scales.
You can intervene by using the after_scale()
function.
A typical use of after_scale()
is to derive colours from colour
to fill
or vice versa.
A nice benefit of using after_scale()
is that you derive colours, so you can still swap out scales.
Another use case can be to create half-geometries.
When you need a combination of direct input, after stat or after scale modifications, you can use stage()
.
stage(x)
is equivalent to x
.stage(after_stat = x)
is equivalent to after_stat(x)
.stage(after_scale = x)
is equivalent to after_scale(x)
.A typical use case is when you want to initialise the aesthetic with one column, and later modify the mapped values.
Another use case is to reposition labels after computing a statistic.
Staging function on their own are inert.
They need to be put in aes()
.
after_stat()
to access variables computed by the stat part of the layer.
after_scale()
to redirect aesthetics after scale mapping.
stage()
to initiate a column and modify it during later stages
⏲️ Exercise 1.2.5
The classic coord_polar()
is succeeded by coord_radial()
.
expand
parameterHelpful to always examine plot in Cartesian coordinates.
p <- ggplot(mpg, aes(y = factor(1), fill = factor(drv))) +
geom_bar() +
# Add labels
stat_count(
aes(label = after_stat(paste0(fill, " =\n", count))),
geom = "text",
position = position_stack(vjust = 0.5)
) +
# Turn off y-axis and legend
scale_y_discrete(guide = "none", name = NULL) +
scale_fill_discrete(guide = "none")
p
Differences between coord_polar()
and coord_radial()
.
Set expand = FALSE
for use in pie charts.
coord_radial()
interfaces with guide system mostly via guide_axis_theta()
. Also note the text angles.
We’re no longer restricted to complete circles.
Switching a pie chart to a donut chart is as easy as setting the inner.radius
argument.
We can combine partial polar coordinates with donuts.
coord_radial()
replaces coord_polar()
start
& end
inner.radius
⏲️ Exercise 1.2.6
Inner axes can be exposed, for all directions or x
or y
individually.
We can confine labels, so inner axes only display tick marks.
Layers have a layout
argument that can be interpreted by facets.
facet_wrap()
and facet_grid()
allow placement at certain panels.
New panel ordering settings in dir
argument.
as.table
is now absorbed in dir
t
, r
, b
, l
t
= topr
= rightb
= bottoml
= left"br"
starts in the bottom-right."br"
grows bottom-to-top before right-to-left.The default order is "lt"
.
axes = "margins"/"all"/"all_x"/"all_y"
axis.labels = "all"/"margins"/"all_x"/"all_y"
layer(layout)
argument
facet_wrap(dir)
sets panel layout
⏲️ Exercise 1.2.7