Копировать определенные значения в векторе, определяемом другим вектором

У меня есть вектор значений (скажем, 1:10), и я хочу повторить в нем определенные значения 2 или более раз, определяемые другим вектором (скажем, c(3,4,6,8)). В этом примере результат будет c(1,2,3,3,4,4,5,6,6,7,8,8,9,10) при повторении 2 раза.

Это должно работать для вектора диапазона произвольной длины (например, 200:600) со вторым вектором, который содержится в первом. Есть ли удобный способ добиться этого?


person sds    schedule 03.04.2017    source источник
comment
может быть лучше сделать ваш пример вектора более случайным, чем 1:10, так как вы хотите, чтобы он работал с произвольными векторами   -  person talat    schedule 03.04.2017
comment
Да, верно. Пример, который мне действительно нужен, также отсортирован, поэтому я добавлю его к вопросу.   -  person sds    schedule 03.04.2017


Ответы (4)


Метод Акруна более компактный, но и он сработает.

# get rep vector
reps <- rep(1L, 10L)
reps[c(3,4,6,8)] <- 2L

rep(1:10, reps)
 [1]  1  2  3  3  4  4  5  6  6  7  8  8  9 10

Понимание здесь заключается в том, что rep будет принимать целочисленный вектор во втором аргументе той же длины, что и первый аргумент, который указывает количество повторений для каждого элемента первого аргумента.

Обратите внимание, что это решение основано на предположении, что c(3,4,6,8) — это индекс или позиция повторяющихся элементов. В этом сценарии комментарий db имеет однострочный

rep(x, (seq_along(x) %in% c(3,4,6,8)) + 1)

Если вместо этого c(3,4,6,8) указывает значения, которые должны повторяться, то сверхкомпактный код docendo-discimus,

rep(x, (x %in% c(3,4,6,8)) * (n-1) +1)

где n можно регулировать для изменения количества повторений. Если вам нужно вызвать это пару раз, это можно свернуть в функцию, например

myReps <- function(x, y, n) rep(x, (x %in% y) * (n-1) +1)

и называется как

myReps(1:10, c(3,4,6,8), 2)

в текущем сценарии.

person lmo    schedule 03.04.2017
comment
Это можно было бы сократить до rep(x, (x %in% y) * (n-1) +1), предполагая, что x — исходный вектор, y — повторяющиеся элементы, а n — количество повторений, где n>1 - person talat; 03.04.2017
comment
Это также может быть возможным вариантом: rep(x, (seq_along(x) %in% r) + 1), где r = c(3,4,6,8) и x = 1:10 - person d.b; 03.04.2017
comment
@db, это неверно (или только для очень конкретного случая, когда x = 1:10). Например, попробуйте с x = sample(1:10) или x = 16:22: - person talat; 03.04.2017
comment
@docendodiscimus, я (возможно, ошибочно) предположил, что r является индексом повторяемых значений. Но если r не является индексом, то вы можете просто сделать rep(x, (x %in% r) + 1) - person d.b; 03.04.2017
comment
@d.b., тогда это будет ограничено 2 повторениями, но OP хочет, чтобы это повторялось 2 или более раз - person talat; 03.04.2017

Мы можем попробовать

i1 <- v1 %in% v2
sort(c(v1[!i1], rep(v1[i1], each = 2)))
#[1]  1  2  3  3  4  4  5  6  6  7  8  8  9 10

Обновлять

Для произвольного вектора

f1 <- function(vec1, vec2, n){
i1 <- vec1 %in% vec2
vec3 <- seq_along(vec1)
 c(vec1[!i1], rep(vec1[i1], each = n))[order(c(vec3[!i1], 
            rep(vec3[i1], each=n)))]
 }

set.seed(24)
v1N <- sample(10)
v2 <- c(3,4,6,8)
v1N
#[1]  3 10  6  4  7  5  2  9  8  1

f1(v1N, v2, 2)
#[1]  3  3 10  6  6  4  4  7  5  2  9  8  8  1
f1(v1N, v2, 3)
#[1]  3  3  3 10  6  6  6  4  4  4  7  5  2  9  8  8  8  1
person akrun    schedule 03.04.2017

Вот еще один подход с использованием sapply

#DATA
x = 1:10
r = c(3,4,6,8)
n = 2 #Two repetitions of selected values

#Assuming 'r' is the index of values in x to be repeated
unlist(sapply(seq_along(x), function(i) if(i %in% r){rep(x[i], n)}else{rep(x[i],1)}))
#[1]  1  2  3  3  4  4  5  6  6  7  8  8  9 10

#Assuming 'r' is the values in 'x' to be repeated
unlist(sapply(x, function(i) if(i %in% r){rep(i, n)}else{rep(i, 1)}))
#[1]  1  2  3  3  4  4  5  6  6  7  8  8  9 10

Не проверял их тщательно, но могут быть возможные альтернативы. Обратите внимание, что при таком подходе порядок вывода будет значительно отличаться.

sort(c(x, rep(x[x %in% r], n-1))) #assuming 'r' is values
#[1]  1  2  3  3  4  4  5  6  6  7  8  8  9 10
sort(c(x, rep(x[r], n-1))) #assuming 'r' is index
#[1]  1  2  3  3  4  4  5  6  6  7  8  8  9 10
person d.b    schedule 03.04.2017
comment
ни одно из ваших решений не работает для произвольного вектора. например x<-c(9L, 7L, 8L, 4L, 1L, 6L, 2L, 10L, 5L, 3L), r <- c(3,4,6,8) и n<-2 - person 989; 04.04.2017

Я предлагаю это решение только для того, чтобы подчеркнуть классное использование функции append в базе R:

ff <- function(vec, v, n) {
    for(i in seq_along(v)) vec <- append(vec, rep(v[i], n-1), after = which(vec==v[i]))
    vec
}

Примеры:

set.seed(1)

ff(vec = sample(10), v = c(3,4,6,8), n = 2)
#[1]  3  3  4  4  5  7  2  8  8  9  6  6 10  1

ff(vec = sample(10), v = c(2,5,9), n = 4)
#[1]  3  2  2  2  2  6 10  5  5  5  5  7  8  4  1  9  9  9  9
person 989    schedule 03.04.2017