2

Suppose I have three vectors a.1, a.2, a.3 -- they could hold arbitrary values (meaning the values would not necessarily be sorted)

> a.1 <- seq(1,15,3)
> a.2 <- seq(15,2,-3)
> a.3 <- seq(2,15,3)
> a.1
[1]  1  4  7 10 13
> a.2
[1] 15 12  9  6  3
> a.3
[1]  2  5  8 11 14

Now I want to produce a new vector C where I take all elements of a except elements at indices 2, 3, 5 and only elements at indices 2, 3 from vector a.2 and element at index 5 from a.3; combine them in order

One way I know how to do this is:

> C <- a.1
> C[c(2,3)] <- a.2[c(2,3)]
> C[5] <- a.3[5]
> C
[1]  1 12  9 10 14

I wonder if there are are better ways of doing this -- better may include:

  1. More elegant
  2. Extendable to say splices from multiple elements
  3. More Terse (syntax wise)

Notes

  1. One of the answer authors has suggested using replace -- I wonder if replace can be used in multiway splices
  2. Also note the vales in the source or target vector need not be sorted
  3. It would be great if the same solution can be used (barring some minor modifications) on both vectors and dataframes
user1172468
  • 5,088
  • 6
  • 32
  • 61

2 Answers2

4

In this case, I'd just use a boring old loop and overwrite the corresponding indexes from each object:

multchange <- function(x, repl, idx) {
  for (i in seq_along(repl)) {
    x[idx[[i]]] <- repl[[i]][idx[[i]]]
  }
  x
}

df_list <- list(a.2, a.3)
cool_list <- list(c(2,3), 5)
multchange(a.1, df_list, cool_list)
#[1]  1 12  9 10 14

And no, using a loop is not slower on a large dataset:

samp <- rep(1:2,each=1000000)
df_list <- list(a.2, a.3)[samp]
cool_list <- list(c(2,3), 5)[samp]

system.time({
  multchange(a.1, df_list, cool_list)
})
#   user  system elapsed 
#   4.24    0.00    4.25 

c <- a.1
system.time({
  mapply(function(X, Y) { c[Y] <<- X[Y] }, X=df_list, Y=cool_list)
})
#   user  system elapsed 
#   7.46    0.00    7.49 
thelatemail
  • 85,757
  • 12
  • 122
  • 177
2
df_list <- list(a.2, a.3)
cool_list <- list(c(2,3), 5)
c <- a.1
mapply(function(X, Y) { c[Y] <<- X[Y] }, X=df_list, Y=cool_list)
AidanGawronski
  • 1,965
  • 1
  • 12
  • 24