Vectorization insert element
I wrote an R function to insert a given element E at a given position P of vector v
Here is:
insert <- function(v,e,p) { if (length(e) != 1 || length(p) != 1) { stop('supported the insertion of only one element per call.') } len <- length(v) nms <- names(v) enm <- names(e) res <- NULL if (p > 1 && p <= len) { res <- c(v[1:(p-1)],v[p:len]) # insert } else if (p == 1) { res <- c(e,v) # prepend } else if (p == (len+1)) { res <- c(v,e) # append } else { stop('wrong position') } if (!is.null(enm)) { names(res) <- insert(nms,enm,p) } res }
Note that this function, like almost everything in R, returns a new vector In addition (see recursive call), it also inserts the name of the element, if any
This is a simple example:
a <- c(1,2,3,4,5,7,8,10) names(a) <- c(letters[1:5],letters[7:8],letters[10]) a # a b c d e g h j # 1 2 3 4 5 7 8 10 b <- c(9) names(b) <- letters[9] insert(a,b,8) # a b c d e g h i j # 1 2 3 4 5 7 8 9 10
I am trying to write a vectorized (efficient) version of this function
Now I have written an elegant solution:
vinsert <- function(v,elems,positions) { out <- v for (i in 1:length(elems)) { out <- insert(out,elems[i],positions[i]) } out }
Here is a simple example:
a <- c(1,letters[10]) a # a b c d e g h j # 1 2 3 4 5 7 8 10 z <- c(6,9) names(z) <- c(letters[6],letters[9]) z # f i # 6 9 vinsert(a,z,z) # a b c d e f g h i j # 1 2 3 4 5 6 7 8 9 10
Therefore, the two functions I am considering (insert and vinsert) are:
>Return a new vector or modify the vector and return it? > Write an equivalent function with rcpp? > Can I write an equivalent function using a first-order R function?
Any suggestions, help or more elegant and effective solutions? Thank you in advance
Solution
There seem to be many problems, such as how the insertion order is affected by previous insertion and what to do when inserting a sequence of more than one element Here we have a primitive sequence
x <- letters[1:10]
And what we want to insert
v <- LETTERS[1:4]
Where we want to insert them
at <- c(4,6)
One way to insert is to calculate the order of the new index value relative to the original value; Orders provide stable orders
o <- order(c(seq_along(x),at))
Then insert
> c(x,v)[o] [1] "a" "b" "C" "c" "d" "A" "e" "f" "D" "g" "B" "h" "i" "j"
The insertion rule is not exactly the same as the original insertion rule
> o = order(c(seq_along(a),z)) > c(a,z)[o] a b c d e g f h j i 1 2 3 4 5 7 6 8 10 9