Interlacing two vectors
You can rbind
them, then coerce back to a vector.
a <- c("a1", "a2", "a3")
b <- c("b1", "b2", "b3")
c(rbind(a,b))
# [1] "a1" "b1" "a2" "b2" "a3" "b3"
As @Moody_Mudskipper points out, as.vector(rbind(a,b)))
is faster
For the case when the lengths are different, I found the following solution from Rolf Turner at this link: http://r.789695.n4.nabble.com/Interleaving-elements-of-two-vectors-td795123.html
riffle <- function (a,b) {
n <- min(length(a),length(b))
p1 <- as.vector(rbind(a[1:n],b[1:n]))
p2 <- c(a[-(1:n)],b[-(1:n)])
c(p1,p2)
}
riffle(1:3, letters[1:5])
# [1] "1" "a" "2" "b" "3" "c" "d" "e"
Alternate, interweave or interlace two vectors
Your rbind
method should work well. You could also use
rpois(lambda=c(3,4),n=1e6)
because R will automatically replicate the vector of lambda values to the required length. There's not much difference in speed:
library(rbenchmark)
benchmark(rpois(1e6,c(3,4)),
c(rbind(rpois(5e5,3),rpois(5e5,4))))
# test replications elapsed relative
# 2 c(rbind(rpois(5e+05, 3), rpois(5e+05, 4))) 100 23.390 1.112168
# 1 rpois(1e+06, c(3, 4)) 100 21.031 1.000000
and elegance is in the eye of the beholder ... of course, the c(rbind(...))
method works in general for constructing alternating vectors, while the other solution is specific to rpois
or other functions that replicate their arguments in that way.
How do I interlace two Rust vectors into a new vector?
Using interleave()
function or interleave()
method from Itertools crate:
use itertools::{interleave, Itertools};
fn main() {
let v1 = vec![1.0, 2.0, 3.0];
let v2 = vec![4.0, 5.0, 6.0];
let v = interleave(v1, v2).collect::<Vec<_>>();
dbg!(v);
let v1 = vec![1.0, 2.0, 3.0];
let v2 = vec![4.0, 5.0, 6.0];
let v = v1
.into_iter()
.interleave(v2.into_iter())
.collect::<Vec<_>>();
dbg!(v);
}
Interweave two columns into one in r
If you wrap the c
function around a matrix object (which is what df
is above), it will "unwrap them in column-dominant manner (except it needs to be created with rbind
so that the interleaving will occur):
c(rbind(col1,col2))
[1] 1 5 2 6 3 7 4 8
If you want it to print at the console as though it were a "column vector" in matrix parlance you could `cbind that result to get a one column matrix object:
cbind( c(rbind(col1,col2)) )
[,1]
[1,] 1
[2,] 5
[3,] 2
[4,] 6
[5,] 3
[6,] 7
[7,] 4
[8,] 8
Alternate, interweave or interlace two matrices
Here are two alternatives.
First, assuming we have to start with "x" and "y", you can try interleave
from the "gdata" package:
library(gdata)
interleave(x, y)
# ranks names
# [1,] "1" "Karl"
# [2,] "" "Cape Town"
# [3,] "2" "Klaus"
# [4,] "" "London"
# [5,] "3" "Mary"
# [6,] "" "Berlin"
Second, assuming we can start with "ranks", "names", and "universities", you can use base R, like this:
cbind(c(t(cbind(ranks, ""))), c(t(cbind(names, universities))))
# [,1] [,2]
# [1,] "1" "Karl"
# [2,] "" "Cape Town"
# [3,] "2" "Klaus"
# [4,] "" "London"
# [5,] "3" "Mary"
# [6,] "" "Berlin"
A better alternative, however, would be to use something like melt
(from "reshape2" or "data.table"). This would allow you to add another variable that indicates what type of measurement a value represents.
library(data.table)
melt(data.table(ranks, names, universities), "ranks")
# ranks variable value
# 1: 1 names Karl
# 2: 2 names Klaus
# 3: 3 names Mary
# 4: 1 universities Cape Town
# 5: 2 universities London
# 6: 3 universities Berlin
Or, to match your desired ordering:
library(data.table)
setorder(melt(data.table(ranks, names, universities), "ranks"), ranks)[]
# ranks variable value
# 1: 1 names Karl
# 2: 1 universities Cape Town
# 3: 2 names Klaus
# 4: 2 universities London
# 5: 3 names Mary
# 6: 3 universities Berlin
How to merge 2 vectors alternating indexes?
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
Packing and de-interleaving two __m256 registers
// __m256 lo = a0 b0 a1 b1 a2 b2 a3 b3 // load proximal elements
// __m256 hi = a4 b4 a5 b5 a6 b6 a7 b7
// __m256 colA = a0 a1 a2 a3 a4 a5 a6 a7 // goal
// __m256 colB = b0 b1 b2 b3 b4 b5 b6 b7
It seems we can do this shuffle even faster than my orginal answer:
void unpack_cols(__m256i lo, __m256i hi, __m256i& colA, __m256i& colB) {
const __m256i mask = _mm256_setr_epi32(0, 2, 4, 6, 1, 3, 5, 7);
// group cols crossing lanes:
// a0 a1 a2 a3 b0 b1 b2 b3
// a4 a5 a6 a7 b4 b5 b6 b7
auto lo_grouped = _mm256_permutevar8x32_epi32(lo, mask);
auto hi_grouped = _mm256_permutevar8x32_epi32(hi, mask);
// swap lanes:
// a0 a1 a2 a3 a4 a5 a6 a7
// b0 b1 b2 b3 b4 b5 b6 b7
colA = _mm256_permute2x128_si256(lo_grouped, hi_grouped, 0 | (2 << 4));
colB = _mm256_permute2x128_si256(lo_grouped, hi_grouped, 1 | (3 << 4));
}
While both instructions have a 3 cycles latency on Haswell (see Agner Fog) they have a single cycle throughput. This means it has a throughput of 4 cycles and 8 cycles latency. If you have a spare register which can keep the mask this should be better. Doing only two of these in parallel allows you to completly hide its latency. See godbolt and rextester.
Old answer, kept for reference:
The fastest way to do this shuffle is the following:
void unpack_cols(__m256i lo, __m256i hi, __m256i& colA, __m256i& colB) {
// group cols within lanes:
// a0 a1 b0 b1 a2 a3 b2 b3
// a4 a5 b4 b5 a6 a7 b6 b7
auto lo_shuffled = _mm256_shuffle_epi32(lo, _MM_SHUFFLE(3, 1, 2, 0));
auto hi_shuffled = _mm256_shuffle_epi32(hi, _MM_SHUFFLE(3, 1, 2, 0));
// unpack lo + hi a 64 bit
// a0 a1 a4 a5 a2 a3 a6 a7
// b0 b1 b4 b5 b2 b3 b6 b7
auto colA_shuffled = _mm256_unpacklo_epi64(lo_shuffled, hi_shuffled);
auto colB_shuffled = _mm256_unpackhi_epi64(lo_shuffled, hi_shuffled);
// swap crossing lanes:
// a0 a1 a2 a3 a4 a5 a6 a7
// b0 b1 b2 b3 b4 b5 b6 b7
colA = _mm256_permute4x64_epi64(colA_shuffled, _MM_SHUFFLE(3, 1, 2, 0));
colB = _mm256_permute4x64_epi64(colB_shuffled, _MM_SHUFFLE(3, 1, 2, 0));
}
Starting with Haswell this has a throughput of 6 cycles (sadly six instructions on port 5). According to Agner Fog _mm256_permute4x64_epi64
has a latency of 3 cycles. This means unpack_cols
has a latency of 11 8 cycles.
You can check the code on godbolt.org or test it at rextester which has AVX2 support but sadly no permalinks like godbolt.
Note that this is also very close to the problem I had where I gathered 64 bit ints and needed the high and low 32 bits separated.
Note that gather performance is really bad in Haswell but according to Agner Fog Skylake got a lot better at it (~12 cycles throughput down to ~5). Still shuffling around such simple patterns should still be a lot faster than gathering.
Interleave lists in R
Here's one way:
idx <- order(c(seq_along(a), seq_along(b)))
unlist(c(a,b))[idx]
# [1] "a.1" "b.1" "a.2" "b.2" "a.3" "b.3" "b.4"
As @James points out, since you need a list back, you should do:
(c(a,b))[idx]
Related Topics
R: Web Scraping Yahoo.Finance After 2019 Change
Shiny - Checkbox in Table in Shiny
Reverse and Change Limit of Axis
How to Create a World Map in R with Specific Countries Filled In
Data.Table Package in R 3.5 Does Not Install
How to Use Ggplot2's Geom_Dotplot() with Both Fill and Group
How to Download and Display an Image from an Url in R
Different Colors for Each Bar in Stacked Bar Graph - Base Graphics
Explicitly Set Panel Size (Not Just Plot Size) in Ggplot2
Passing Arguments to Ggplot in a Wrapper
Print to PDF File Using Grid.Table in R - Too Many Rows to Fit on One Page
Ggplot2 - Using Two Different Color Scales for Overlayed Plots
Recommended Way to Initialize Js Renderer in 'Asis' R Markdown Chunk
How to Read Huge CSV File into R by Row Condition
Weird Characters Added to First Column Name After Reading a Toad-Exported CSV File
R: What's the How to Overwrite a Function from a Package
How to Use Loess Method in Ggally::Ggpairs Using Wrap Function