I would like to merge 2 vectors this way :
a = c(1,2,3)
b = c(11,12,13)
merged vector : c(1,11,2,12,3,13)
How could I do it ?
I would like to merge 2 vectors this way :
a = c(1,2,3)
b = c(11,12,13)
merged vector : c(1,11,2,12,3,13)
How could I do it ?
This will work using rbind
:
c(rbind(a, b))
For example:
a = c(1,2,3)
b = c(11,12,13)
c(rbind(a,b))
#[1] 1 11 2 12 3 13
This works because R stores arrays in column-major order.
When you rbind()
the two vectors, you get:
rbind_result <- rbind(a, b)
rbind_result
# [,1] [,2] [,3]
# a 1 2 3
# b 11 12 13
Then c()
coerces rbind_result
into a column-wise flattened vector:
merged <- c(rbind_result)
merged
# [1] 1 11 2 12 3 13
The rbind()
answer by @jalapic is excellent. Here's an alternative that creates a new vector then assigns the alternating values to it.
a <- c(1,2,3)
b <- c(11,12,13)
x <- vector(class(a), length(c(a, b)))
x[c(TRUE, FALSE)] <- a
x[c(FALSE, TRUE)] <- b
x
# [1] 1 11 2 12 3 13
And one more that shows append
c(sapply(seq_along(a), function(i) append(a[i], b[i], i)))
# [1] 1 11 2 12 3 13
Just wanted to add a simpler solution that works for when vectors are unequal length and you want to append the extra data to the end.
> a <- 1:3
> b <- 11:17
> c(a, b)[order(c(seq_along(a)*2 - 1, seq_along(b)*2))]
[1] 1 11 2 12 3 13 14 15 16 17
Explanation:
c(a, b)
creates a vector of the values in a
and b
.seq_along(a)*2 - 1
creates a vector of the first length(a)
odd numbers.seq_along(b)*2
creates a vector of the first length(b)
even numbers.order(...)
will return the indexes of the numbers in the two seq_along
vectors such that x[order(x)]
is an ordered list. Since the first seq_along
contains the even numbers and the second seq_along
has the odds, order will take the first element from the first seq_along
, then the first elements of the second seq_along
, then the second element from the first seq_along
, etc. interspersing the two vector indexes and leaving the extra data at the tail.c(a, b)
using the order
vector, we will intersperse a
and b
.As a note, since seq_along
returns numeric(0)
when the input is NULL
this solution works even if one of the vectors is length 0
.
I had to solve a similar problem, but my vectors were of unequal length. And, I didn't want to recycle the shorter vector, but just append the tail of the longer vector.
And the solution for @RichardScriven didn't work for me (though I may have done something wrong and didn't try hard to troubleshoot).
Here is my solution:
#' Riffle-merges two vectors, possibly of different lengths
#'
#' Takes two vectors and interleaves the elements. If one vector is longer than
#' the other, it appends on the tail of the longer vector to the output vector.
#' @param a First vector
#' @param b Second vector
#' @return Interleaved vector as described above.
#' @author Matt Pettis
riffle <- function(a, b) {
len_a <- length(a)
len_b <- length(b)
len_comm <- pmin(len_a, len_b)
len_tail <- abs(len_a - len_b)
if (len_a < 1) stop("First vector has length less than 1")
if (len_b < 1) stop("Second vector has length less than 1")
riffle_common <- c(rbind(a[1:len_comm], b[1:len_comm]))
if (len_tail == 0) return(riffle_common)
if (len_a > len_b) {
return(c(riffle_common, a[(len_comm + 1):len_a]))
} else {
return(c(riffle_common, b[(len_comm + 1):len_b]))
}
}
# Try it out
riffle(1:7, 11:13)
[1] 1 11 2 12 3 13 4 5 6 7
riffle(1:3, 11:17)
[1] 1 11 2 12 3 13 14 15 16 17
HTH, Matt
A tidyverse
approach is vctrs::vec_interleave
:
vctrs::vec_interleave(a, b)
#[1] 1 11 2 12 3 13
@MBo's answer to my question at https://stackoverflow.com/a/58773002/2556061 implies a solution for evenly interlacing vectors of unequal length. I'm reporting it here in for reference.
interleave <- function(x, y)
{
m <- length(x)
n <- length(y)
xi <- yi <- 1
len <- m + n
err <- len %/% 2
res <- vector()
for (i in 1:len)
{
err <- err - m
if (err < 0)
{
res[i] <- x[xi]
xi <- xi + 1
err <- err + len
} else
{
res[i] <- y[yi]
yi <- yi + 1
}
}
res
}
gives
interleave(1:10, 100:120)
c(100, 1, 101, 102, 2, 103, 104, 3, 105, 106, 4, 107, 108, 5, 109, 110, 111, 6, 112, 113, 7, 114, 115, 8, 116, 117, 9, 118, 119, 10, 120)