Physical Constants in R

Physical constants in R

The packages marelac and dielectric both have some physical constants, but not that one in particular. marelac::convert_T will do the temperature conversions.

universal constants in R

pi (note the lowercase) is defined but e is not, although exp(1) is obviously available.

pi
# [1] 3.141593

The small number of built-in constants are described :

?Constants

It would be possible to cure this lack-of-e problem with this code:

e <- exp(1)
lockBinding("e", globalenv())
e
#[1] 2.718282
e <- 2.5
#Error: cannot change value of locked binding for 'e'

(Thanks to Hadley for illustrating this in a different SO thread.)
You probably also should go to:

?NumericConstants

Where you will read among other things: "A numeric constant immediately followed by i is regarded as an imaginary complex number."

The other important constants are TRUE and FALSE, and while T and F can be used in a clean session, T and F are not reserved and can be assigned other values, which will then provoke difficult to debug errors, so their use is deprecated. (Although, I suppose one could also use the lockBinding strategy on them as well.)

There are a few character "constants", such as the 26 item character vectors: letters, LETTERS, as well as 12 months in your locale: month.abb and month.name. The Greek letters (lower and uppercase) and some math notation can be accessed via methods described in ?plotmath.

The state.name and state.abb mentioned by Tyler below are actually part of the (USA) state dataset in the "datasets" package which is loaded by default:

library(help="datasets")

If you see an example that uses the cars, chickwts, iris or any of the other dataframes in "datasets", as many help() examples do, these objects can be assumed to be available on any R user's machine.

How to get the Planck constant in R?

library(ChargeTransport)

# Return the Planck constant in J.s
universalConstants["h","Value"]

# Return the Planck constant in eV.s
Joule2electronVolt(universalConstants["h","Value"])

If you want directly the Angular Planck constant:

# in J.s
universalConstants["hbar","Value"]

# in eV.s
Joule2electronVolt(universalConstants["hbar","Value"])

Declaring a Const Variable in R

See lockBinding:

a <- 1
lockBinding("a", globalenv())
a <- 2
Error: cannot change value of locked binding for 'a'

Can I use R attributes to save physical units?

You can, with this code:

attributes(epsilon0) <- list(name = "electric constant", source = "CODATA", unit="F m-1")

how to save frequently used physical constants in python

Inheriting from class float, you have to overwrite the __new__-method:

class Constant(float):
def __new__(cls, value, units, doc):
self = float.__new__(cls, value)
self.units = units
self.doc = doc
return self

R = Constant(287.102, "J/(kg K)", "deal gas constant")

print R, R * 2
>>> 287.102 574.204
print R.units
>>> J/(kg K)
print R.doc
>>> ideal gas constant

Benefits of using integer values for constants rather than numeric values (e.g. 1L vs 1) in R

These are some of the use cases in which I explicitly use the L suffix in declaring the constants. Of course these are not strictly "canonical" (or the only ones), but maybe you can have an idea of the rationale behind. I added, for each case, a "necessary" flag; you will see that these arise only if you interface other languages (like C).

  • Logical type conversion (not necessary)

Instead of using a classic as.integer, I use adding 0L to a logical vector to make it integer. Of course you could just use 0, but this would require more memory (typically 8 bytes instead of four) and a conversion.

  • Manipulating the result of a function that returns integer (not necessary)

Say for instance that you want to find to retrieve the elements of the vector after a NA. You could:

which(is.na(vec)) + 1L

Since which returns an integer, adding 1L will preserve the type and avoid an implicit conversion. Nothing will happen if you omit the L, since it's just a small optimization. This happens also with match for instance: if you want to post-process the result of such a function, it's good habit to preserve the type if possible.

  • Interfacing C (necessary)

From ?integer:

Integer vectors exist so that data can be passed to C or Fortran
code which expects them, and so that (small) integer data can be
represented exactly and compactly.

C is much stricter regarding data types. This implies that, if you pass a vector to a C function, you can not rely on C to do the conversions. Say that you want to replace the elements after a NA with some value, say 42. You find the positions of the NA values at the R level (as we did before with which) and then pass the original vector and the vector of indices to C. The C function will look like:

SEXP replaceAfterNA (SEXP X, SEXP IND) {
...
int *ind = INTEGER(IND);
...
for (i=0; i<l; i++) {
//make here the replacement
}
}

and the from the R side:

...
ind <- which(is.na(x)) + 1L
.Call("replaceAfterNA", x, ind)
...

If you omit the L in the first line of above, you will receive an error like:

INTEGER() cannot be applied to double vectors

since C is expecting an integer type.

  • Interfacing Java (necessary)

Same as before. If you use the rJava package and want R to call your own custom Java classes and methods, you have to be sure that an integer is passed when the Java method requires an integer. Not adding a specific example here, but it should be clear why you may want to use the L suffix in constants in these cases.

Addendum

The previous cases where about when you may want to use L. Even if I guess much less common, it might be useful to add a case in which you don't want the L. This may arise if there is danger of integer overflow. The *, + and - operators preserve the type if both the operand are integer. For example:

#this overflows
31381938L*3231L
#[1] NA
#Warning message:
#In 31381938L * 3231L : NAs produced by integer overflow

#this not
31381938L*3231
#[1] 1.01395e+11

So, if you are doing operations on an integer variable which might produce overflow, it's important to cast it to double to avoid any risk. Adding/subtracting to that variable a constant without the L might be a good occasion as any to make the cast.

What's the difference between `1L` and `1`?

So, @James and @Brian explained what 3L means. But why would you use it?

Most of the time it makes no difference - but sometimes you can use it to get your code to run faster and consume less memory. A double ("numeric") vector uses 8 bytes per element. An integer vector uses only 4 bytes per element. For large vectors, that's less wasted memory and less to wade through for the CPU (so it's typically faster).

Mostly this applies when working with indices.
Here's an example where adding 1 to an integer vector turns it into a double vector:

x <- 1:100
typeof(x) # integer

y <- x+1
typeof(y) # double, twice the memory size
object.size(y) # 840 bytes (on win64)

z <- x+1L
typeof(z) # still integer
object.size(z) # 440 bytes (on win64)

...but also note that working excessively with integers can be dangerous:

1e9L * 2L # Works fine; fast lean and mean!
1e9L * 4L # Ooops, overflow!

...and as @Gavin pointed out, the range for integers is roughly -2e9 to 2e9.

A caveat though is that this applies to the current R version (2.13). R might change this at some point (64-bit integers would be sweet, which could enable vectors of length > 2e9). To be safe, you should use .Machine$integer.max whenever you need the maximum integer value (and negate that for the minimum).



Related Topics



Leave a reply



Submit