R - manage your R profile
18 May 2018
We all face moments where we feel as not being as smart as expected. You know, those times where we lack of spirit presence, and of connection with the real world. It sometimes happen with R too, and that’s the subject of today’s post. Let’s focus on some reccuring needs, and how to address them gracefully in a very concise and convenient way.
Shuffling a vector
Real need, recurring and generally solution has to be rediscovered at each time.
#R code
shuffle <- function(x_v) x_v[order(runif(length(x_v)))]
This function allows to shuffle any vector, even empty ones, as c()
is another way to say NULL
.
#R test session
> shuffle(c())
NULL
> shuffle(1:15)
[1] 6 3 4 8 13 15 5 10 2 11 1 14 7 9 12
Nota Bene: shuffling does not imply that each item will change. Know it! If you need an absolute shuffle, this function is not the right one.
Matrix display in reverse order
Let’s consider a n*m matrix. Of course, using print
allows to print the matrix. But how to print it in reverse order of rows?
#R code
revmat <- function(x_m) apply(x_m, 2, rev)
This will do the job
#R test session
> ma <- matrix(1:63, nrow = 7, byrow = TRUE)
> ma
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] 1 2 3 4 5 6 7 8 9
[2,] 10 11 12 13 14 15 16 17 18
[3,] 19 20 21 22 23 24 25 26 27
[4,] 28 29 30 31 32 33 34 35 36
[5,] 37 38 39 40 41 42 43 44 45
[6,] 46 47 48 49 50 51 52 53 54
[7,] 55 56 57 58 59 60 61 62 63
> revmat(ma)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] 55 56 57 58 59 60 61 62 63
[2,] 46 47 48 49 50 51 52 53 54
[3,] 37 38 39 40 41 42 43 44 45
[4,] 28 29 30 31 32 33 34 35 36
[5,] 19 20 21 22 23 24 25 26 27
[6,] 10 11 12 13 14 15 16 17 18
[7,] 1 2 3 4 5 6 7 8 9
Determining if a number is a whole number
I call a whole number a pure integer. So, how do you determine in R if a number is a whole number?
#R trial session
> is.integer(1)
FALSE
> is.integer(1L)
TRUE
I would have expected each of these to answer true. R manual recommends to use following R function to determine if a number is a whole number
#R code from R manual page is.integer
is.wholenumber <- function(x, tol = .Machine$double.eps^0.5) abs(x - round(x)) < tol
Again, not what I expect, as this does have some undesirable side effects. See below
#R test session
> e <- exp(1)
> l <- list(-3L, 0L, 48L, -2, 1, pi, 1 + 1i, 1 - 1i, complex(r = pi, i = e),
TRUE, FALSE, 1L + TRUE, 1L + FALSE, 1.1 + TRUE, 1.1 + FALSE)
> dt <- data.table(text = as.character(l), whole = sapply(l, is.wholenumber))
> dt
text whole
1: -3 TRUE
2: 0 TRUE
3: 48 TRUE
4: -2 TRUE
5: 1 TRUE
6: 3.14159265358979 FALSE
7: 1+1i TRUE
8: 1-1i TRUE
9: 3.14159265358979+2.71828182845905i FALSE
10: TRUE TRUE
11: FALSE TRUE
12: 2 TRUE
13: 1 TRUE
14: 2.1 FALSE
15: 1.1 FALSE
>
So, complex numbers are whole numbers if their real and imaginary parts are whole numbers. Strange, and not what I expect. So what is the correct, implementation to know if a number is an integer number?
DON’T: use is.wholenumber
to test for a whole number as it appears insufficiently restrictive to do so.
#R code
> isAnIntegerNumber <- function(x) is.numeric(x) & is.wholenumber(x)
> dk <- data.table(text = as.character(l), whole = sapply(l, isAnIntegerNumber))
> dk
text whole
1: -3 TRUE
2: 0 TRUE
3: 48 TRUE
4: -2 TRUE
5: 1 TRUE
6: 3.14159265358979 FALSE
7: 1+1i FALSE
8: 1-1i FALSE
9: 3.14159265358979+2.71828182845905i FALSE
10: TRUE FALSE
11: FALSE FALSE
12: 2 TRUE
13: 1 TRUE
14: 2.1 FALSE
15: 1.1 FALSE
>
Finally, we got the right answer. This one is really counter intuitive and not so easy to remind.
DO: use isAnIntegerNumber
to test for a whole number as it appears insufficient restrictive to do so.
TIP: those functions are good candidates for your .Rprofile
.