[This ERC is based on the blog post Automatic units in axis labels, published under CC-BY license.]
This blog post concerns the development version of units, installed by
devtools::install_github("edzer/units")
Have you ever tried to properly add measurement units to R plots? It might go like this:
xlab = parse(text = "temperature ~~ group('[', degree * C, ']')") ylab = parse(text = "speed ~~ group('[', m * ~~ s^-1, ']')") par(mar = par("mar") + c(0, .3, 0, 0)) # avoids cutting of superscript plot(3 + 1:10 + 2 * rnorm(10), xlab = xlab, ylab = ylab)
The main observation is, of course that it can be done. However,
Although well-written help is found in ?plotmath
, all three observations cause frustration.
The original paper desribing plotmath
is by Paul Murrell and Ross Ihaka. R core member Paul Murrell also wrote package grid
, part of base R. Few people use it directly, but without it ggplot2 or lattice could not exist.
The new units CRAN package now makes working with units
Here is an example using mtcars
. First, we specify the imperial units to those known in the udunits2 database:
library(units) gallon = make_unit("gallon") consumption = mtcars$mpg * with(ud_units, mi/gallon) displacement = mtcars$disp * ud_units[["in"]]^3
For displacement
, we cannot use the normal lookup in the database
displacement = mtcars$disp * with(ud_units, in)
because in
(inch) is also a reserved word in R.
We convert these values to SI units by
units(displacement) = with(ud_units, cm^3) units(consumption) = with(ud_units, km/l) consumption[1:5]
We can plot these numeric variabes of type units
by
par(mar = par("mar") + c(0, .1, 0, 0)) # avoids cutting of brackets at lhs plot(displacement, consumption)
The units automatically appear in axis labels! If we want to have negative power instead of division bars, we can set a global option
units_options(negative_power = TRUE) # division becomes ^-1
Expressions such as
1/displacement [1:10]
automatically convert units, which also happens in plots (note the converted units symbols):
par(mar = par("mar") + c(0, .3, 0, 0)) plot(1/displacement, 1/consumption)
We can of course plot these data by dropping units:
library(ggplot2) ggplot() + geom_point(aes(x = as.numeric(displacement), y = as.numeric(consumption)))
but that doesn't show us units. Giving the units as variables gives an error:
ggplot() + geom_point(aes(x = displacement, y = consumption))
(I could make that error go away by letting units
drop the
requirement that in a comparison both sides should have compatible
units, which of course would be wrong.)
We can then go all the way with
ggplot() + geom_point(aes(x = as.numeric(displacement), y = as.numeric(consumption))) + xlab(make_unit_label("displacement", displacement)) + ylab(make_unit_label("consumption", consumption))
which at least doesn't cut off the left label, but feels too convoluted and error-prone.
Oh ggplot gurus, who can help us out, here? How can we obtain that last plot by
ggplot() + geom_point(aes(x = displacement, y = consumption))
?
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.