Replicating specific values in a vector defined by another vector
I have a vector of values (say 1:10
) and want to repeat certain values in it 2 or more times, defined by another vector (say c(3,4,6,8)
). In this example, the result will be c(1,2,3,3,4,4,5,6,6,7,8,8,9,10)
when repeated 2 times.
This should work for an arbitrary length-of-length vector (e.g. 200:600
), with the second vector contained first. Is there a convenient way to achieve this?
source to share
Akrun is a more compact method, but this will also work
# 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
The understanding here is that it rep
will accept an integer vector in the second argument of the same length as the first argument, which indicates the number of times to repeat for each element of the first argument.
Note that this decision is based on the assumption of what c(3,4,6,8)
is the index or position of the items to be repeated. In this case, db comment has a one-line
rep(x, (seq_along(x) %in% c(3,4,6,8)) + 1)
If instead c(3,4,6,8)
specifies values to be repeated, then docendo-discimus is a super compact code,
rep(x, (x %in% c(3,4,6,8)) * (n-1) +1)
where n can be adjusted to change the number of repetitions. If you need to call this a couple of times it can be folded into a function like
myReps <- function(x, y, n) rep(x, (x %in% y) * (n-1) +1)
and called
myReps(1:10, c(3,4,6,8), 2)
in the current scenario.
source to share
We can try
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
Update
For an arbitrary vector
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
source to share
Here's a different approach using 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
Didn't test these thoroughly but there might be alternatives. Note that the order of output will vary significantly with this approach.
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
source to share
I suggest this solution to just highlight the cool use of the function append
in R base:
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
}
Examples:
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
source to share