R has little support for physical measurement units. The exception is formed by time differences: time differences objects of class `difftime`

have a `units`

attribute that can be modified:

```
t1 = Sys.time()
t2 = t1 + 3600
d = t2 - t1
class(d)
## [1] "difftime"
units(d)
## [1] "hours"
d
## Time difference of 1 hours
units(d) = "secs"
d
## Time difference of 3600 secs
```

We see here that the `units`

method is used to retrieve and modify the unit of time differences.

This idea can be generalized to other physical units. The `units`

package, presented here, does this, and builds upon the udunits2 R package, which in turn is build upon the udunits2 C library. The `udunits2`

library provides the following operations:

- validating whether a string, such as
`m/s`

is a valid physical unit - verifying whether two strings such as
`m/s`

and`km/h`

are convertible - converting values between two convertible units
- providing names and symbols for specific units
- handle different character encodings (utf8, ascii, iso-8859-1 and latin1)

Th `units`

R package uses R package udunits2 to extend R with functionality for manipulating numeric vectors that have physical measurement units associated with them, in a similar way as `difftime`

objects behave.

Units must be defined before they are used. Units are defined from a string but by explicitly defining units before they are used we avoid having new units in use due to misspellings. A unit is defined using the `make_units`

function

```
library(units)
m <- make_unit("m")
s <- make_unit("s")
```

The objects created,

```
m
## 1 m
```

represent a single value of the named quantity (``m’’). To obtain different quantities of named units, we use them in expressions such as

```
(a <- 1:10 * m/s)
## Units: m/s
## [1] 1 2 3 4 5 6 7 8 9 10
```

the result, e.g.

```
a[10]
## 10 m/s
```

literally means “10 times 1 m divided by 1 s”. In writing, the “1” values are omitted, and the multiplication is implicit.

The `units`

package comes with a list of over 3000 predefined units, which can be used without calling `make_unit`

. One way of making this list available would be to attach it, but this leads to a number of name conflicts: `T`

(for tesla) wound mask the value that otherwise refers to `TRUE`

, .

A cleaner approach is to use `with`

, as in

```
rm(m) ; rm(s)
with(ud_units, 1:10 * m/s)
## Units: m/s
## [1] 1 2 3 4 5 6 7 8 9 10
```

When conversion is meaningful, such as hours to seconds or meters to kilometers, conversion can be done explicitly by setting the units of a vector

```
b = a
units(b) <- with(ud_units, km/h)
b
## Units: km/h
## [1] 3.6 7.2 10.8 14.4 18.0 21.6 25.2 28.8 32.4 36.0
```

Arithmetic operations verify units, and create new ones

```
a + a
## Units: m/s
## [1] 2 4 6 8 10 12 14 16 18 20
a * a
## Units: m^2/s^2
## [1] 1 4 9 16 25 36 49 64 81 100
a ^ 2
## Units: m^2/s^2
## [1] 1 4 9 16 25 36 49 64 81 100
a ** -2
## Units: s^2/m^2
## [1] 1.00000000 0.25000000 0.11111111 0.06250000 0.04000000 0.02777778
## [7] 0.02040816 0.01562500 0.01234568 0.01000000
```

and convert to the units of the first argument if necessary:

```
a + b # m/s + km/h -> m/s
## Units: m/s
## [1] 2 4 6 8 10 12 14 16 18 20
```

Currently, powers are only supported for integer powers, so using `a ** 2.5`

would result in an error.

There are some basic simplification of units:

```
t <- with(ud_units, s)
a * t
## Units: m
## [1] 1 2 3 4 5 6 7 8 9 10
```

which also work when units need to be converted before they can be simplified:

```
t <- with(ud_units, min)
a * t
## Units: m
## [1] 60 120 180 240 300 360 420 480 540 600
```

Simplification to unit-less values gives the “1” as unit:

```
m <- with(ud_units, m)
a * t / m
## Units: 1
## [1] 60 120 180 240 300 360 420 480 540 600
```

Allowed operations that require convertible units are `+`

, `-`

, `==`

, `!=`

, `<`

, `>`

, `<=`

, `>=`

. Operations that lead to new units are `*`

, `/`

, and the power operations `**`

and `^`

.

Mathematical operations allowed are: `abs`

, `sign`

, `floor`

, `ceiling`

, `trunc`

, `round`

, `signif`

, `log`

, `cumsum`

, `cummax`

, `cummin`

.

```
signif(a ** 2 / 3, 3)
## Units: m^2/s^2
## [1] 0.333 1.330 3.000 5.330 8.330 12.000 16.300 21.300 27.000 33.300
cumsum(a)
## Units: m/s
## [1] 1 3 6 10 15 21 28 36 45 55
log(a) # base defaults to exp(1)
## Units: ln(m/s)
## [1] 0.0000000 0.6931472 1.0986123 1.3862944 1.6094379 1.7917595 1.9459101
## [8] 2.0794415 2.1972246 2.3025851
log(a, base = 10)
## Units: lg(m/s)
## [1] 0.0000000 0.3010300 0.4771213 0.6020600 0.6989700 0.7781513 0.8450980
## [8] 0.9030900 0.9542425 1.0000000
log(a, base = 2)
## Units: lb(m/s)
## [1] 0.000000 1.000000 1.584963 2.000000 2.321928 2.584963 2.807355
## [8] 3.000000 3.169925 3.321928
```

Summary functions `sum`

, `min`

, `max`

, and `range`

are allowed:

```
sum(a)
## 55 m/s
min(a)
## 1 m/s
max(a)
## 10 m/s
range(a)
## Units: m/s
## [1] 1 10
with(ud_units, min(m/s, km/h)) # converts to first unit:
## 0.2777778 m/s
```

Following `difftime`

, printing behaves differently for length-one vectors:

```
a
## Units: m/s
## [1] 1 2 3 4 5 6 7 8 9 10
a[1]
## 1 m/s
```

The usual subsetting rules work:

```
a[2:5]
## Units: m/s
## [1] 2 3 4 5
a[-(1:9)]
## 10 m/s
```

```
c(a,a)
## Units: m/s
## [1] 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
```

concatenation converts to the units of the first argument, if necessary:

```
c(a,b) # m/s, km/h -> m/s
## Units: m/s
## [1] 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
c(b,a) # km/h, m/s -> km/h
## Units: km/h
## [1] 3.6 7.2 10.8 14.4 18.0 21.6 25.2 28.8 32.4 36.0 3.6 7.2 10.8 14.4
## [15] 18.0 21.6 25.2 28.8 32.4 36.0
```

`difftime`

From `difftime`

to `units`

:

```
t1 = Sys.time()
t2 = t1 + 3600
d = t2 - t1
du <- as.units(d)
```

vice versa:

```
dt = as.dt(du)
class(dt)
## [1] "difftime"
dt
## Time difference of 1 hours
```

`matrix`

objects```
with(ud_units, matrix(1:4,2,2) * m/s)
## Units: m/s
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
with(ud_units, matrix(1:4,2,2) * m/s * 4 * m/s)
## Units: m^2/s^2
## [,1] [,2]
## [1,] 4 12
## [2,] 8 16
```

but

```
with(ud_units, (matrix(1:4,2,2) * m/s) %*% (4:3 * m/s))
## [,1]
## [1,] 13
## [2,] 20
```

strips units.

`data.frame`

sunits in `data.frame`

objects are printed, but do not appear in `summary`

:.

```
set.seed(131)
d <- with(ud_units,
data.frame(x = runif(4),
y = runif(4) * s,
z = 1:4 * m/s))
d
## x y z
## 1 0.2064370 0.8463468 s 1 m/s
## 2 0.1249422 0.5292048 s 2 m/s
## 3 0.2932732 0.5186254 s 3 m/s
## 4 0.3757797 0.2378545 s 4 m/s
summary(d)
## x y z
## Min. :0.1249 Min. :0.2379 Min. :1.00
## 1st Qu.:0.1861 1st Qu.:0.4484 1st Qu.:1.75
## Median :0.2499 Median :0.5239 Median :2.50
## Mean :0.2501 Mean :0.5330 Mean :2.50
## 3rd Qu.:0.3139 3rd Qu.:0.6085 3rd Qu.:3.25
## Max. :0.3758 Max. :0.8463 Max. :4.00
d$yz = with(d, y * z)
d
## x y z yz
## 1 0.2064370 0.8463468 s 1 m/s 0.8463468 m
## 2 0.1249422 0.5292048 s 2 m/s 1.0584095 m
## 3 0.2932732 0.5186254 s 3 m/s 1.5558761 m
## 4 0.3757797 0.2378545 s 4 m/s 0.9514180 m
d[1, "yz"]
## 0.8463468 m
```

Units are often written in the form `m2 s-1`

, for square meter per second. This can be defined as unit, but is not interpreted by R:

```
(x = 1:10 * make_unit("m2 s-1"))
## Units: (m2 s-1)
## [1] 1 2 3 4 5 6 7 8 9 10
```

udunits understands such string, and can convert them

```
y = 1:10 * with(ud_units, m^2/s)
x + y
## Units: (m2 s-1)
## [1] 2 4 6 8 10 12 14 16 18 20
```

but R cannot simplify them:

```
x/y
## Units: (m2 s-1)*s/m^2
## [1] 1 1 1 1 1 1 1 1 1 1
```

Instead, we can tell R to parse such a string, which then allows simplification:

```
(z = 1:10 * parse_unit("m2 s-1"))
## Units: m^2/s
## [1] 1 2 3 4 5 6 7 8 9 10
z + y
## Units: m^2/s
## [1] 2 4 6 8 10 12 14 16 18 20
z / y
## Units: 1
## [1] 1 1 1 1 1 1 1 1 1 1
```

Printing units in this form is done by

```
as_cf(z)
## [1] "m2 s-1"
```

Base scatter plots and histograms support automatic unit placement in axis labels. In the following example we first convert to SI units. (Unit `in`

needs a bit special treatment, because `in`

is a reserved word in R.)

```
mar = par("mar") + c(0, .3, 0, 0)
displacement = mtcars$disp * ud_units[["in"]]^3
units(displacement) = with(ud_units, cm^3)
weight = mtcars$wt * 1000 * with(ud_units, lb)
units(weight) = with(ud_units, kg)
par(mar = mar)
plot(weight, displacement)
```

We can change grouping symbols from `[ ]`

into `( )`

:

```
units_options(group = c("(", ")") ) # parenthesis instead of square brackets
par(mar = mar)
plot(weight, displacement)
```

We can also remove grouping symbols, increase space between variable name and unit by:

```
units_options(sep = c("~~~", "~"), group = c("", "")) # no brackets; extra space
par(mar = mar)
plot(weight, displacement)
```

More complex units can be plotted either with negative powers, or as divisions, by modifying one of `units`

’s global options using `units_options`

:

```
gallon = make_unit("gallon")
consumption = mtcars$mpg * with(ud_units, mi/gallon)
units(consumption) = with(ud_units, km/l)
par(mar = mar)
plot(displacement, consumption) # division in consumption
```

```
units_options(negative_power = TRUE) # division becomes ^-1
plot(displacement, consumption) # division in consumption
```

As usual, units modify automatically in expressions:

```
units_options(negative_power = TRUE) # division becomes ^-1
par(mar = mar)
plot(displacement, consumption)
```

`plot(1/displacement, 1/consumption)`