在特定位置上用另一个向量的元素替换一个向量的元素

时间:2016-04-24 10:20:15

标签: r vector

我有以下数据:

orig.vec <- c(1:10)
idx      <- c(3,5,6)
rep.vec  <- list(c(7,7,7), c(8,8,8), c(9,9,9))

第一。如何将rep.vec的元素插入orig.vecidx所包含的位置,并将orig.vec值移至左/右?

期望的结果:

  1. orig.vec向右移动:1,2,7,7,7,3,4,8,8,8,5,9,9,9,6,7,8,9,10
  2. orig.vec向左移动:1,2,3,7,7,7,4,5,8,8,8,6,9,9,9,7,8,9,10
  3. 第二。如何使用orig.vec的元素替换idx中包含的位置rep.vec的元素?

    期望的结果:

    1,2,7,7,7,4,8,8,8,9,9,9,7,8,9,10

4 个答案:

答案 0 :(得分:2)

第一和第二部分

lst <- split(orig.vec,cumsum(seq_along(orig.vec) %in% idx))
lst1 <- split(orig.vec,cumsum(seq_along(orig.vec) %in% (idx+1)))

i1 <- seq_along(rep.vec)
unlist(c(Map(c, lst[i1], rep.vec), lst[setdiff(seq_along(lst), i1)]), use.names=FALSE)
#[1]  1  2  7  7  7  3  4  8  8  8  5  9  9  9  6  7  8  9 10

unlist(c(Map(c, lst1[i1], rep.vec), lst1[setdiff(seq_along(lst1), i1)]), use.names=FALSE)
#[1]  1  2  3  7  7  7  4  5  8  8  8  6  9  9  9  7  8  9 10

第三部分可以使用

完成
lst <- split(seq_along(orig.vec),cumsum(seq_along(orig.vec) %in% idx))
i2 <- sapply(lst, function(i) any(i %in% idx))
lst[i2] <- Map(c, rep.vec, lapply(lst[i2], `[`, -1))
unlist(lst, use.names=FALSE)
#[1]  1  2  7  7  7  4  8  8  8  9  9  9  7  8  9 10

另一种选择是使用append

idx1 <- idx+c(0,lengths(rep.vec)[-1])
for(i in seq_along(rep.vec)){
orig.vec <- append(orig.vec, rep.vec[[i]], after = idx1[i]-1)
}
orig.vec
#[1]  1  2  7  7  7  3  4  8  8  8  5  9  9  9  6  7  8  9 10

在上面的循环中替换after = idx1[i](重置'orig.vec'后给出

orig.vec
#[1]  1  2  3  7  7  7  4  5  8  8  8  6  9  9  9  7  8  9 10

第三部分

 v1 <- orig.vec[-idx]
 for(i in seq_along(rep.vec)){
   v1 <- append(v1, rep.vec[[i]], after = idx1[i]-i)
 }
 v1
 #[1]  1  2  7  7  7  4  8  8  8  9  9  9  7  8  9 10

答案 1 :(得分:2)

与akrun后来发布的解决方案没什么不同,但是将orig.vec转换为“列表”以附加另一个“列表”的元素会使连接/替换更清晰:

ff = function(x, v, i) 
{ 
     if(!length(i)) return(unlist(x)) 
     Recall(append(as.list(x), v[1L], i[[1L]]), v[-1L], i[-1L])
}
#1
ff(orig.vec, rep.vec, idx + seq_along(idx) - 2L)
# [1]  1  2  7  7  7  3  4  8  8  8  5  9  9  9  6  7  8  9 10
#2
ff(orig.vec, rep.vec, idx + seq_along(idx) - 1L)
# [1]  1  2  3  7  7  7  4  5  8  8  8  6  9  9  9  7  8  9 10
#3 here, simply, replace between two "list"s
unlist(replace(as.list(orig.vec), idx, rep.vec))
# [1]  1  2  7  7  7  4  8  8  8  9  9  9  7  8  9 10

请注意,对于非常大的对象,连续级联通常很麻烦。

答案 2 :(得分:2)

另一种可能的方法:

doit<-function(orig.vec,idx,rep.vec,how){
    left <- c(1,idx + (how != "R"))
    right <- c(idx - (how != "L"),length(orig.vec))
    parts <- apply(cbind(left,right),1,
        function(x) if(x[1]>x[2]) c() else orig.vec[x[1]:x[2]])
    unlist(c(lapply(1:length(idx),
        function(x) c(parts[[x]],rep.vec[[x]])),
            tail(parts,1)))
}

> doit(orig.vec,idx,rep.vec,"R")
 [1]  1  2  7  7  7  3  4  8  8  8  5  9  9  9  6  7  8  9 10
> doit(orig.vec,idx,rep.vec,"L")
 [1]  1  2  3  7  7  7  4  5  8  8  8  6  9  9  9  7  8  9 10
> doit(orig.vec,idx,rep.vec,"X")
 [1]  1  2  7  7  7  4  8  8  8  9  9  9  7  8  9 10

答案 3 :(得分:2)

orig.vec <- c(1:10)
idx      <- c(3,5,6)
rep.vec  <- list(c(7,7,7), c(8,8,8), c(9,9,9))


left  <- Map('c', idx, rep.vec)
right <- Map('c', rep.vec, idx)
repl  <- rep.vec

l <- as.list(orig.vec)
l[idx] <- left
l[idx] <- right
l[idx] <- repl
unlist(l)

## left
# [1]  1  2  3  7  7  7  4  5  8  8  8  6  9  9  9  7  8  9 10
## right
# [1]  1  2  7  7  7  3  4  8  8  8  5  9  9  9  6  7  8  9 10
## repl
# [1]  1  2  7  7  7  4  8  8  8  9  9  9  7  8  9 10

编辑:作为一个功能

insert <- function(x, index, replacement, how = c('replace','left','right')) {
  how <- match.arg(how)
  repl <- switch (how,
    replace = replacement,
    left = Map('c', index, replacement),
    right = Map('c', replacement, index)
  )
  x[index] <- repl
  unlist(x)
}

sapply(c('replace','left','right'), insert,
       x = orig.vec, index = idx, replacement = rep.vec)

# $replace
#  [1]  1  2  7  7  7  4  8  8  8  9  9  9  7  8  9 10
# 
# $left
#  [1]  1  2  3  7  7  7  4  5  8  8  8  6  9  9  9  7  8  9 10
# 
# $right
#  [1]  1  2  7  7  7  3  4  8  8  8  5  9  9  9  6  7  8  9 10