2016-04-24 4 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.vec в положениях, содержащихся в idx, и сдвинуть 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

второй. Как я могу заменить элементы orig.vec в положениях, содержащихся в idx элементами rep.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 

Edit: как функция

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] < - оставил; unlist (л); l [idx] <- right; unlist (л); l [idx] <- repl; unlist (l) ' –

+0

@WakanTanka yep, я просто показывал, как они могут быть использованы. для полноты, вы можете написать функцию, см. правки – rawr

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 

Еще о 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