2016-04-24 69 views
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)) 

第一。如何将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

第二。我如何用rep.vec的元素在idx中包含的位置替换orig.vec的元素?

期望的结果:

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

回答

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 
+0

似乎是最好的解决方法,但是我曾与替换最后4行:'升[IDX] < - 剩下;不公开(升); l [idx] < - right;不公开(升); l [idx] < - repl; unlist(l)' –

+0

@WakanTanka是的,我只是展示了它们各自如何被使用。为了完整起见,您可以编写一个函数,参见编辑 – rawr

2

对于使用

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 

另一个O在第一和第二部分

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 

第三部分是可以做到ption将是使用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 
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

另一种可能的方法中:

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 
相关问题