You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: vignettes/measurement_units_in_R.html
+25-59
Original file line number
Diff line number
Diff line change
@@ -282,7 +282,7 @@ <h4 class="author">Edzer Pebesma, Thomas Mailund, and James Hiebert</h4>
282
282
</ul>
283
283
<div id="abstract" class="section level2">
284
284
<h2>Abstract</h2>
285
-
<p>We briefly review SI units, and discuss R packages that deal with measurement units, their compatibility and conversion. Built upon <a href="https://cran.r-project.org/package=udunits2">udunits2</a> and the UNIDATA udunits library, we introduce the package <a href="https://cran.r-project.org/package=units">units</a> that provides a class for maintaining unit metadata. When used in expression, it automatically converts units, and simplifies units of results when possible; in case of incompatible units, errors are raised. The class flexibly allows expansion beyond predefined units. Using <a href="https://cran.r-project.org/package=units">units</a> may eliminate a whole class of potential scientific programming mistakes. We discuss the potential and limitations of computing with explicit units.</p>
285
+
<p>We briefly review SI units, and discuss R packages that deal with measurement units, their compatibility and conversion. Built upon the UNIDATA udunits library, we introduce the package <a href="https://cran.r-project.org/package=units">units</a> that provides a class for maintaining unit metadata. When used in expression, it automatically converts units, and simplifies units of results when possible; in case of incompatible units, errors are raised. The class flexibly allows expansion beyond predefined units. Using <a href="https://cran.r-project.org/package=units">units</a> may eliminate a whole class of potential scientific programming mistakes. We discuss the potential and limitations of computing with explicit units.</p>
<p>Both <a href="https://cran.r-project.org/package=measurements">measurements</a> and <a href="https://cran.r-project.org/package=NISTunits">NISTunits</a> are written entirely in R.</p>
<p>Udunits, developed by UCAR/UNIDATA, advertises itself on <a href="https://www.unidata.ucar.edu/software/udunits/">its web page</a> as: “<em>The udunits package supports units of physical quantities. Its C library provides for arithmetic manipulation of units and for conversion of numeric values between compatible units. The package contains an extensive unit database, which is in XML format and user-extendable.</em>”</p>
432
-
<p>The R package <a href="https://cran.r-project.org/package=udunits2">udunits2</a> <span class="citation">(<a href="#ref-udunits2" role="doc-biblioref">Hiebert 2015</a>)</span> provides a low-level R interface to the most important functions in the udunits2 C library.</p>
433
-
<p>The functions provided by <a href="https://cran.r-project.org/package=udunits2">udunits2</a> are</p>
<p>and <code>get.name</code>, <code>get.symbol</code> and <code>set.encoding</code> get name, get symbol or modify encoding of the character unit arguments.</p>
453
-
<pre class="r"><code>ud.get.name("kg")
454
-
## [1] "kilogram"
455
-
ud.get.symbol("kilogram")
456
-
## [1] "kg"
457
-
ud.set.encoding("utf8")
458
-
## NULL</code></pre>
459
-
<p>Unlike the <a href="https://cran.r-project.org/package=measurements">measurements</a> and <a href="https://cran.r-project.org/package=NISTunits">NISTunits</a>, <a href="https://cran.r-project.org/package=udunits2">udunits2</a> parses units as expressions, and bases its logic upon the convertibility of expressions, rather than the comparison of fixed strings:</p>
432
+
<p>Unlike the <a href="https://cran.r-project.org/package=measurements">measurements</a> and <a href="https://cran.r-project.org/package=NISTunits">NISTunits</a>, the underlying udunits2 C library parses units as expressions, and bases its logic upon the convertibility of expressions, rather than the comparison of fixed strings:</p>
<p>This has the advantage that through complex computations, intermediate objects can have units that are arbitrarily complex, and that can potentially be simplified later on. It also means that the package practically supports an unlimited amount of derived units.</p>
469
438
</div>
@@ -479,57 +448,57 @@ <h2>Handling data with units in R: the units package</h2>
479
448
<pre class="r"><code>library(units)
480
449
x = set_units(1:5, m/s)
481
450
str(x)
482
-
## Units: [m*s^-1] int [1:5] 1 2 3 4 5</code></pre>
451
+
## Units: [m/s] int [1:5] 1 2 3 4 5</code></pre>
483
452
<p>represents speed values in <code>m/s</code>. The units <code>m</code> and <code>s</code> are resolved from the udunits2 C library (but could be user-defined units).</p>
484
453
<p>Units can be used in arbitrary R expressions like</p>
485
454
<pre class="r"><code>set_units(1:3, m/s^2)
486
-
## Units: [m*s^-2]
455
+
## Units: [m/s^2]
487
456
## [1] 1 2 3</code></pre>
488
457
<p>Several manipulations with <code>units</code> objects will now be illustrated. Manipulations that do not involve unit conversion are for instance addition:</p>
489
458
<pre class="r"><code>x = set_units(1:3, m/s)
490
459
x + 2 * x
491
-
## Units: [m*s^-1]
460
+
## Units: [m/s]
492
461
## [1] 3 6 9</code></pre>
493
462
<p>Explicit unit conversion is done by assigning new units:</p>
494
463
<pre class="r"><code>(x = set_units(x, cm/s))
495
-
## Units: [cm*s^-1]
464
+
## Units: [cm/s]
496
465
## [1] 100 200 300
497
466
as.numeric(x)
498
467
## [1] 100 200 300</code></pre>
499
468
<p>similar to the behaviour of <code>difftime</code> objects, this modifies the numeric values without modifying their meaning (what the numbers refer to).</p>
500
469
<p>When mixing units in sums, comparisons or concatenation, units are automatically converted to those of the first argument:</p>
501
470
<pre class="r"><code>y = set_units(1:3, km/h)
502
471
x + y
503
-
## Units: [cm*s^-1]
472
+
## Units: [cm/s]
504
473
## [1] 127.7778 255.5556 383.3333
505
474
y + x
506
-
## Units: [km*h^-1]
475
+
## Units: [km/h]
507
476
## [1] 4.6 9.2 13.8
508
477
x == y
509
478
## [1] FALSE FALSE FALSE
510
479
c(y, x)
511
-
## Units: [km*h^-1]
480
+
## Units: [km/h]
512
481
## [1] 1.0 2.0 3.0 3.6 7.2 10.8</code></pre>
513
482
<p>where <code>c(y, x)</code> concatenates <code>y</code> and <code>x</code> after converting <code>x</code> to the units of <code>y</code>. Derived units are created where appropriate:</p>
514
483
<pre class="r"><code>x * y
515
-
## Units: [cm*km*h^-1*s^-1]
484
+
## Units: [cm*km/h/s]
516
485
## [1] 100 400 900
517
486
x^3
518
-
## Units: [cm^3*s^-3]
487
+
## Units: [cm^3/s^3]
519
488
## [1] 1.0e+06 8.0e+06 2.7e+07</code></pre>
520
489
<p>and meaningful error messages appear when units are not compatible:</p>
521
490
<pre class="r"><code>e = try(z <- x + x * y)
522
-
## Error : cannot convert cm*km*h^-1*s^-1 into cm*s^-1
491
+
## Error : cannot convert cm*km/h/s into cm/s
523
492
attr(e, "condition")[[1]]
524
-
## [1] "cannot convert cm*km*h^-1*s^-1 into cm*s^-1"</code></pre>
493
+
## [1] "cannot convert cm*km/h/s into cm/s"</code></pre>
525
494
<p>The full set of methods and method groups for <code>units</code> objects is shown by</p>
## see '?methods' for accessing help and source code</code></pre>
534
503
<p>where the method groups</p>
535
504
<ul>
@@ -549,10 +518,10 @@ <h2>Handling data with units in R: the units package</h2>
549
518
## 1e+100 [m]</code></pre>
550
519
<p>Units are printed as simple R expressions, e.g.</p>
551
520
<pre class="r"><code>set_units(1, m^5/s^4)
552
-
## 1 [m^5*s^-4]</code></pre>
521
+
## 1 [m^5/s^4]</code></pre>
553
522
<p>Another way to print units commonly seen in Climate and Forecast Conventions is <code>m2 s-1</code> for m<span class="math inline">\(^2\)</span>/s. These are not R expressions, but they can be parsed by <code>as_units</code>, and created by <code>deparse_unit</code>:</p>
554
523
<pre class="r"><code>as_units("m2 s-1")
555
-
## 1 [m^2*s^-1]
524
+
## 1 [m^2/s]
556
525
deparse_unit(set_units(1, m^2*s^-1))
557
526
## [1] "m2 s-1"</code></pre>
558
527
<p>The <code>plot</code> and <code>hist</code> methods add units to default axis labels, an example is shown in the following figures. For <a href="https://cran.r-project.org/package=ggplot2">ggplot2</a> plots <span class="citation">(<a href="#ref-ggplot2" role="doc-biblioref">Wickham 2009</a>)</span>, automatic unit placement in default axis label is also provided; <code>demo(ggplot2)</code> gives an example.</p>
@@ -598,7 +567,7 @@ <h2>Discussion and conclusions</h2>
598
567
<p>The <a href="https://cran.r-project.org/package=units">units</a> R package provides a new class, <code>units</code>, for numeric data with associated measurement units. Operations on objects of this class retain the unit metadata and provide automated dimensional analysis: dimensions are taken into consideration in computations and comparisons. Combining different units that are compatible triggers automatic unit conversion, derived units are automatically generated and simplified where possible, and meaningful error messages are given when a user tries to add objects with incompatible units. This verifies that computations are not only syntactically and numerically allowed, but also semantically, and in the case of physical units, physically allowed, which may support code verification and provenance tracking. Using this package may eliminate a whole class of potential scientific programming mistakes.</p>
599
568
<p>Where the R packages <a href="https://cran.r-project.org/package=measurements">measurements</a> and <a href="https://cran.r-project.org/package=NISTunits">NISTunits</a> provide conversion between a fixed number of units, with the help of the udunits2 C library and unit database, R package <a href="https://cran.r-project.org/package=units">units</a> handles arbitrarily complex derived units. By treating units as expressions it can derive, convert and simplify units. In addition, beyond the SI units packaged, <a href="https://cran.r-project.org/package=units">units</a> handles user-defined units.</p>
600
569
<p>Data in <code>units</code> vectors can be stored as columns in <code>data.frame</code> or <code>tbl_df</code> objects, and can be converted to and from <code>difftime</code>. When <code>units</code> objects have associated time and location information, they could be stored in spatial or spatio-temporal objects provided by <a href="https://cran.r-project.org/package=sp">sp</a> or <a href="https://cran.r-project.org/package=spacetime">spacetime</a> <span class="citation">(<a href="#ref-spacetime" role="doc-biblioref">Pebesma 2012</a>)</span> as these store attribute data in <code>data.frame</code> slots, but for instance not in <code>zoo</code> <span class="citation">(<a href="#ref-zoo" role="doc-biblioref">Zeileis and Grothendieck 2005</a>)</span> or <code>xts</code> <span class="citation">(<a href="#ref-xts" role="doc-biblioref">Ryan and Ulrich 2014</a>)</span> objects, as these latter two set the class attribute of a vector or matrix.</p>
601
-
<p>Despite all standardization efforts, units may still be ambiguous, or subject to interpretation. For instance for the duration of one year <a href="https://cran.r-project.org/package=NISTunits">NISTunits</a> or <a href="https://cran.r-project.org/package=udunits2">udunits2</a> give us an answer that depends on whether we want a common, leap, Gregorian, Julian, tropical or siderial year (<span class="citation"><a href="#ref-lang" role="doc-biblioref">Lang</a> (<a href="#ref-lang" role="doc-biblioref">2006</a>)</span>, see also <code>demo(year)</code>). This illustrates that those who apply unit conversion should be aware of possible pitfalls. Support for calendars in udunits seems not as well developed as in R.</p>
570
+
<p>Despite all standardization efforts, units may still be ambiguous, or subject to interpretation. For instance for the duration of one year <a href="https://cran.r-project.org/package=NISTunits">NISTunits</a> gives us an answer that depends on whether we want a common, leap, Gregorian, Julian, tropical or siderial year (<span class="citation"><a href="#ref-lang" role="doc-biblioref">Lang</a> (<a href="#ref-lang" role="doc-biblioref">2006</a>)</span>, see also <code>demo(year)</code>). This illustrates that those who apply unit conversion should be aware of possible pitfalls. Support for calendars in udunits seems not as well developed as in R.</p>
602
571
<p>Future work includes extending packages that read external data from formats, databases or interfaces with support for measurement unit information into R, preserving the measurement unit information. Examples would be interfaces to HDF5 (e.g., <a href="https://cran.r-project.org/package=h5">h5</a>, <span class="citation"><a href="#ref-h5" role="doc-biblioref">Annau</a> (<a href="#ref-h5" role="doc-biblioref">2016</a>)</span>), <a href="https://cran.r-project.org/package=RNetCDF">RNetCDF</a> <span class="citation">(<a href="#ref-RNetCDF" role="doc-biblioref">Michna and Woods 2016</a>)</span> or <a href="https://cran.r-project.org/package=sos4R">sos4R</a> <span class="citation">(<a href="#ref-sos4R" role="doc-biblioref">Nüst, Stasch, and Pebesma 2011</a>)</span>. It would be nice to see units of measurements propagate into units of regression coefficient estimates.</p>
Grolemund, Garrett, and Hadley Wickham. 2011. <span>“Dates and Times Made Easy with Lubridate.”</span> <em>Journal of Statistical Software</em> 40 (1): 1–25. <a href="https://doi.org/10.18637/jss.v040.i03">https://doi.org/10.18637/jss.v040.i03</a>.
625
594
</div>
626
-
<div id="ref-udunits2" class="csl-entry">
627
-
Hiebert, James. 2015. <em>Udunits2: Udunits-2 Bindings for r</em>.
628
-
</div>
629
595
<div id="ref-iliffe" class="csl-entry">
630
596
Iliffe, Jonathan, and Roger Lott. 2008. <em>Datums and Map Projections: For Remote Sensing, GIS and Surveying</em>. CRC Inc.
0 commit comments