Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
244 lines (185 sloc) 9.2 KB
---
title: "Operations"
date: "`r Sys.Date()`"
output:
rmarkdown::html_vignette:
vignette: >
%\VignetteIndexEntry{Operations}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r, message=FALSE}
library(tidyverse) # load tidyverse tools
library(MediaChemTools) # load the library
options(try.outFile = stdout()) # show error messages in try statements
```
# Units & Metric Scaling
All chemical quantities in this package keep track of the units they represent with a base unit as detailed in the [quantities vignette](quantities.html) and a metric prefix. By default, the metric prefix is adjusted automatically to keep numeric values in a range close to 1. However, scaling to a specific prefix is easily achieved.
```{r}
# automatic scaling
qty(5000, "g") %>% print() # automatically scaled to kg
qty(5000, "g", scale_to_best_metric = FALSE) %>% print() # stays g
# specific scaling
qty(100, "mg") %>% base_metric() %>% print() # scale to the base unit (here g)
qty(100, "mM") %>% base_metric() %>% print() # scale to the base unit (here M)
qty(100, "mg") %>% scale_metric("k") %>% print()
```
The actual numeric value of a quantity can be retrieved via the `get_qty_value()` function which takes an optional parameter to specify which unit the value should be retrieved in (by default it is the unit that the quantity is currently in). Additionally, a transformation function can be specified for easy log or other transformations.
```{r}
qty(100, "mg") %>% get_qty_value() # returns 100
qty(0.1, "g") %>% get_qty_value() # returns 100 because the units are "mg"
qty(0.1, "g") %>% get_qty_value("g") # better to be specific upon retrieval
qty(0.1, "g") %>% get_qty_value("g", log10) # applies a log10 transform
qty(0.1, "g") %>% get_qty_value("kg") # can use any valid unit
qty(0.1, "g") %>% get_qty_value("kg", sqrt) # and any transformation
qty(0, "C") %>% get_qty_value("F") # or use it for unit conversion
qty(760, "Torr") %>% get_qty_value("atm") # or use it for unit conversion
```
To retrieven numeric values as text that includes their units, simply use `get_qty_text()` instead of `get_qty_value()`.
```{r}
# get quantity with unit
qty(100, "mg") %>% get_qty_text()
qty(0:10, "C") %>% get_qty_text("F")
qty(760, "Torr") %>% get_qty_text("atm")
```
To include this type of quantity text in axis tickmark labels, color/shape/linetype scale labels or facet labels, generate a labeller function using `make_qty_text_labeller()` and use it as the `labels` parameter for scales or the `labeller` parameter for facets.
```{r}
# generate labellers for plotting purposes
q <- qty(c(0.1, 1, 1000), "g")
standard_units_labeller <- make_qty_text_labeller(q)
standard_units_labeller(q) %>% print()
specific_units_labeller <- make_qty_text_labeller(q, "g")
specific_units_labeller(q) %>% print()
```
The units of a quantity object can also be retrieved directly with the `get_qty_units()` function for a single quantity, list of quantities as well as entire data frames (see details on the latter in the [data frames section](#data-frames)).
```{r}
qty(5000, "g") %>% get_qty_units()
x <- list(
a = qty(5000, "g"),
b = 42,
c = qty(100, "mbar")
)
x %>% get_qty_units() %>% print()
```
For easy construction of plot axis or legend labels, the function `get_qty_units_with_label()` further provides an easy way to combine labels with the units. By default (for lists and data frames), it uses the names of the list variable/data frame columns (see details on the latter in the [data frames section](#data-frames)).
```{r}
qty(5000, "g") %>% get_qty_units_with_label("weight")
x %>% get_qty_units_with_label() %>% print()
x %>% get_qty_units_with_label("same label") %>% print()
x %>% get_qty_units_with_label(c("apple", "banana", "carrot")) %>% print()
```
# Arithmetic
Several common arithmetic operations are implemented for easy interconversion between quantities. All arithmetic operations also automatically keep track of the units and metric prefixes for correct calculations.
## Addition and Subtraction
Quantities of the same type (e.g. masses, volumes, etc.) can be added or subtracted with proper interpration of the metric prefixes. The resulting quantity will be scaled to the best metric prefix as described above. Attempts to add or subtract non-matching quantities (e.g. mass + volume) or a quantity and a number without units will fail with an error to avoid unexpect behaviour and ambiguous calculations.
```{r}
print(qty(0.003, "g") - qty(2, "mg") + qty(5, "µg")) # 1.005 mg
try(qty(1, "g") + qty(1, "L")) # not allowed
try(qty(1, "g") + 1) # not allowed
```
## Multiplication / Division
Quantities can be multipled/divided by a number. The resulting quantity will be scaled to the best metric prefix. This is most commonly used with multiplication/division by 1000.
```{r}
print(qty(1, "mg") * 1000) # convert mg into g
print(qty(1, "mg") / 1e6) # convert mg into ng
```
Quantities can also be divided by another quantity of the same type (e.g. a mass by another mass) effectively canceling out the units resulting in a regular number (with the metric prefixes properly taken into consideration).
```{r}
# how many mg in a kg?
qty(1, "mg") / qty(1, "kg")
```
Additional multiplications and divisions are possible for specific combinations of quantities as detailed below. These formulas are each implemented for all three possible arrangements.
### Molarity = Amount / Volume
```{r}
print(qty(5, "nmol") / qty(50, "mL")) # calculation molarity
print(qty(5, "nmol") / qty(100, "nM")) # calculate volume
print(qty(100, "nM") * qty(50, "mL")) # calculate amount
```
### Density = Mass / Volume
```{r}
print(qty(5, "ng") / qty(50, "mL")) # calculate density
print(qty(5, "ng") / qty(100, "ng/L")) # calculate volume
print(qty(100, "ng/L") * qty(50, "mL")) # calculate mass
```
### Amount = Mass / Molecular Mass
```{r}
print(qty(10, "g") / qty (50, "g/mol")) # calculate amount
print(qty(10, "g") / qty(200, "mmol")) # calculate molecular mass
print(qty(200, "mmol") * qty (50, "g/mol")) # calculate mass
```
### Solubility = Molarity / Pressure
```{r}
print(qty(10, "mM") / qty(200, "mbar")) # calculate solubility
print(qty(10, "mM") / qty(50, "mM/bar")) # calculate pressure
print(qty(50, "mM/bar") * qty (200, "mbar")) # calculate molarity
```
## Comparisons
Quantities can be compared with all common logic operators (`>`, `>=`, `<`, `<=`, `==`, `!=`) taking the metric scaling properly into consideration. Attempts to compare non-matching quantities (e.g. mass & volume) will fail with an error to avoid unexpect behaviour. Comparisons of quantities with numerics are allowed but it is important to be cautious about these since the metric scaling in quantities affects the numeric value.
```{r}
qty(5, "mg") < qty(1, "g")
qty(5, "mg") > qty(10, "ng")
qty(5, "mg") == qty(0.005, "g")
qty(5, "mg") != qty(5, "g")
try(qty(1, "mg") > qty(1, "L")) # not allowed (different quantities)
qty(1, "mg") == 1 # allowed but important to be careful
qty(0.1, "g") == 0.1 # example of metric scaling affecting the comparison
qty(0.1, "g") == 100 # example of metric scaling affecting the comparison
```
It is important to note that due to machine errors, the `==` is best avoided in favor of more reliable comparisions such as tests that check whether the difference between quantities is smaller than a tiny quantity:
```{r}
(x <- qty(1, "mg"))
(y <- x / 3)
(x2 <- y * 3)
x == x2 # should be identical but is not because of machine precision
abs(x - x2) < qty(1, "fg") # absolute difference smaller than 1 femtogram
```
# Data Frames
Quantities are fully supported in dplyr type data frames and the units of a quantity are displayed underneath the column headers, e.g. `<mg>` to indicate a quantity column that has the units of `mg` (and thus is a mass).
```{r}
data_frame(
weight = qty(1:5, "mg"),
volume = qty(20, "mL")
) %>% print()
```
This also means that all common arithmetic operations are allowed within data frames.
```{r}
df <- data_frame(
weight = qty(1:5, "mg"),
vol = qty(20, "mL"),
mw = qty(500, "g/mol"),
amount = weight / mw,
conc = amount / vol,
new_vol = 50 * qty(20, "mL"),
new_weight = conc * new_vol * mw,
`correct?` = abs(50 * weight - new_weight) < qty(1, "fg")
)
print(df)
```
To get the quantities' units or full labels, simply use `get_qty_units()` and `get_qty_units_with_label()`
```{r}
df %>% get_qty_units() %>% print()
df %>% get_qty_units_with_label() %>% print()
```
# Concatenation
Quantities can be concatenated using the regular `c()` function (or the more explicit `c_qty()`) as long as they are the same type of quantity (e.g. all masses). Concatenation make sure that the metric prefix is taken into consideration and scales the new vector to the best metric of the median.
```{r}
c(
qty(1, "g"),
qty(1:3, "mg"),
qty(2, "g")
) %>% print()
```
# Missing data
Missing data (`NA`), empty vector (`numeric(0)`) and infinity placeholders (`Inf`, `-Inf`) are supported in all quantities and work the same as in any other R vectors.
```{r}
qty(NA, "mg") %>% print()
qty(Inf, "mg") %>% print()
qty(numeric(0), "mg") %>% print()
qty(c(10, NA, -Inf, Inf, numeric(0)), "mg") %>% print()
```
# Miscellaneous
To check whether something is a quantity, use the `is_qty()` function.
```{r}
qty(1, "mg") %>% is_qty() # is a quantity
1 %>% is_qty() # not a quantity
```
You can’t perform that action at this time.