<- seq(0,10) r_arr
I’m always trying to sharpen my JavaScript skills and I thought a good way of doing this would be to turn some data frames I had lying around into JavaScript arrays of objects. What resulted is a love letter to the little R functions that are in actuality powerhouses and make our lives so easy because the best way I’ve seen to write these in JavaScript is, well, cray.
seq
In R the seq function lets us create a sequence of numbers by specifying where to start and where to finish. Done.
In JavaScript, the most concise way I’ve found to do this is create an empty array of the length of your sequence, spread it using ...
so you get keys for each item, and then extract those keys to get a sequence of numbers!
R:
1] 0 1 2 3 4 5 6 7 8 9 10 [
JS:
let js_arr = [...Array(11).keys()]
11) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] (
seq’s by
seq
also has a by
argument, where we can specify by how much to increment the vector. In R if we want to create a sequence that increases by 0.5
we just add another argument by = 0.5
!
However, in JavaScript, the easiest way I’ve found is to take our initial array and multiply each number in the array by 0.5
:
R:
seq(0,length(r_arr)/2, by = 0.5)
0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5
JS:
.map(i => 0.5*i) js_arr
11) [0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5] (
rep
In R we can use the rep function to repeat whatever (5 and 10)
we want in the first argument as many times length(r_arr)
as the second argument.
rep
is by no means limited to two numbers, that just so happen to be divisible by one another, but I leveraged this for my approach. We can take our sequence array and map over it so that for each number we find it’s remainder when divided by two, giving us 0
or 1
. In the case that it is 0
we end up multiplying 5
by 1
, and in the case that the remainder is 1
we multiply 2
by 5
to get 10. This seems like a lot of trickery and problem solving for a little repeating sequence!!!
R:
rep(c(5,10), length(r_arr))
1] 5 10 5 10 5 10 5 10 5 10 5 10 5 10 5 10 5 10 5 10 5 10 [
JS:
.map(i => 5 * (1 + i%2)) js_arr
11) [5, 10, 5, 10, 5, 10, 5, 10, 5, 10, 5] (
Array subsetting
This last one is an ode to subsetting with a special shout out to Nischal Shrestha. If I want to find the third, seventh, and tenth elements in my array, all we need in R are some brackets!
R:
= c(2,6,9) +1 ## +1 will make R == JS
r_subset r_arr[r_subset]
1] 2 6 9 [
JS:
= [2,6,9]
js_subset .filter((_, index) => js_subset.includes(index)); js_arr
3) [2, 6, 9] (
Twitter Update
Unique
@daranzolin reccomended adding unique
to the list! In JavaScript we can pass the entire array into filter
where we can use the logic: (1) return the index of the current letter in the array. This will return the first time we see, “a”, “b”, or “c”. If that is equal to the current index, that means we have a new letter and will keep it, otherwise we can throw that letter away. In R, well, we can just use unique
!
R:
<- c("a", "b", "b", "c", "b", "c")
abc <- unique(abc)
unique print(unique)
1] "a" "b" "c" [
JS:
let abc = ["a", "b", "b", "c", "b", "c"];
let unique = letters.filter((item, i, ar) => ar.indexOf(item) === i);
console.log(unique);
3) ["a", "b", "c"] (
Paste
@MattDzugan bought up the real MVP, paste
: a lovely, vectorized hero. In order to do this in JS my solution was to map over the first vector, and return the letter vector with the same index of the number vector:
R:
<- c("a", "b", "c")
abc <- c(1:3)
numb paste(abc, numb)
1] "a 1" "b 2" "c 3" [
JS:
let abc = ["a", "b", "c"]
let numb = [1,2,3]
.map((letter, i) => (letter + " " + numb[i])) abc
3) ["a 1", "b 2", "c 3"] (
In this post I’m focusing on base R functions because I can write an entire tome on translating tidyverse functions and ggplot2
…. In short thank your local R developer, and it’s pretty fun to push yourself to write functions in other languages!
Have any other operations you’d like to add? Find me on twitter and I’d love to add it!