# How to "transpose" a vector of vectors?

**URL:** https://discourse.julialang.org/t/how-to-transpose-a-vector-of-vectors/71085
**Category:** General Usage
**Tags:** arrays
**Created:** [November 7, 2021, 9:52am UTC](https://discourse.julialang.org/t/how-to-transpose-a-vector-of-vectors/71085 "2021-11-07T09:52:09Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![tp2750](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tp2750/32/207806_2.png) [@tp2750](https://discourse.julialang.org/u/tp2750)
#### Post date: [November 7, 2021, 9:52am UTC](https://discourse.julialang.org/t/how-to-transpose-a-vector-of-vectors/71085/1 "2021-11-07T09:52:09Z")

</div>

I have a vector V1 of length `m` where each element is a vector of length `n`.  
How do I “transpose” that into a vector V2 of length `n` where each element is a vector of length `m` and `V2[i][j] == V1[j][i]`?

As an example:

```julia
V1 = [rand(3) for x in 1:10]
V2 = [[x[1] for x in V1], [x[2] for x in V1], [x[3] for x in V1]]
julia> V1[7][2] == V2[2][7]
true

```

This is doable for `n` small, but there must be a more general solution.

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [November 7, 2021, 9:59am UTC](https://discourse.julialang.org/t/how-to-transpose-a-vector-of-vectors/71085/2 "2021-11-07T09:59:21Z")

</div>

Try TensorCast:

```julia
using TensorCast
@cast V2[i][j] := V1[j][i]

```

---

<div class="post-metadata">

### Author: ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)
#### Post date: [November 7, 2021, 10:01am UTC](https://discourse.julialang.org/t/how-to-transpose-a-vector-of-vectors/71085/3 "2021-11-07T10:01:17Z")

</div>

> [@tp2750](#):
>
> ```julia
> V1 = [rand(3) for x in 1:10]
> V2 = [[x[1] for x in V1], [x[2] for x in V1], [x[3] for x in V1]]
> julia> V1[7][2] == V2[2][7]
> 
> ```

This would also work if all vectors have the same length

```julia
V2 = [[x[i] for x in V1] for i in eachindex(V1[1])]

```

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [November 7, 2021, 10:10am UTC](https://discourse.julialang.org/t/how-to-transpose-a-vector-of-vectors/71085/4 "2021-11-07T10:10:11Z")

</div>

Also:

```julia
V2 = collect(eachrow(reduce(hcat, V1)))

```

---

<div class="post-metadata">

### Author: ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)
#### Post date: [November 7, 2021, 10:56am UTC](https://discourse.julialang.org/t/how-to-transpose-a-vector-of-vectors/71085/5 "2021-11-07T10:56:26Z")

</div>

```julia
using SplitApplyCombine

V2 = invert(V1)

```

This `invert` function is pretty general:

> Take a nested container `a` and return a container where the nesting is reversed, such that `invert(a)[i][j] === a[j][i]` .
> 
> Currently implemented for combinations of `AbstractArray` , `Tuple` and `NamedTuple` . It is planned to add `AbstractDict` in the future.

---

<div class="post-metadata">

### Author: ![tp2750](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tp2750/32/207806_2.png) [@tp2750](https://discourse.julialang.org/u/tp2750)
#### Post date: [November 7, 2021, 12:35pm UTC](https://discourse.julialang.org/t/how-to-transpose-a-vector-of-vectors/71085/6 "2021-11-07T12:35:23Z")

</div>

Thank you all. This is such a great community!  
So much to choose from.  
I’ll definitely look more into [TensorCast.jl](https://github.com/mcabbott/TensorCast.jl) and [SplitApplyCombine.jl](https://github.com/JuliaData/SplitApplyCombine.jl)

Here’s a quick comparison, where especially TensorCast is really impressive:

```julia
using TensorCast, SplitApplyCombine

function transpose_tensor(V1)
    @cast V2[i][j] := V1[j][i]
    V2
end

function transpose_comprehension(V1)
    [[x[i] for x in V1] for i in eachindex(V1[1])]
end

function transpose_funct(V1)
    collect(eachrow(reduce(hcat, V1)))
end

function transpose_invert(V1)
    invert(V1)
end

using BenchmarkTools

julia> @btime transpose_tensor(data) setup=(data=[rand(5) for x in 1:500]);
  545.250 ns (4 allocations: 344 bytes)

julia> @btime transpose_comprehension(data) setup=(data=[rand(5) for x in 1:500]);
  6.287 μs (6 allocations: 20.44 KiB)

julia> @btime transpose_funct(data) setup=(data=[rand(5) for x in 1:500]);
  5.119 μs (3 allocations: 19.92 KiB)

julia> @btime transpose_invert(data) setup=(data=[rand(5) for x in 1:500]);
  5.318 μs (6 allocations: 20.44 KiB)

```

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [November 7, 2021, 7:58pm UTC](https://discourse.julialang.org/t/how-to-transpose-a-vector-of-vectors/71085/7 "2021-11-07T19:58:21Z")

</div>

Please note that the `:=` syntax in TensorCast returns a view, thus the greater speed observed. If `|=` was used to create a copy, then the time would be comparable to the other solutions. @mcabbott can advise.

---

<div class="post-metadata">

### Author: ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)
#### Post date: [November 7, 2021, 8:08pm UTC](https://discourse.julialang.org/t/how-to-transpose-a-vector-of-vectors/71085/8 "2021-11-07T20:08:12Z")

</div>

You can also use [ArraysOfArrays.jl](https://github.com/JuliaArrays/ArraysOfArrays.jl%5D "full disclosure: self-advertising, it's my package :-"). It gives you a compact memory representation of nested arrays that you can operate on very efficiently:

```julia
julia> using ArraysOfArrays, BenchmarkTools

julia> V1 = [rand(3) for x in 1:10];

julia> V1aoa = @btime ArrayOfSimilarArrays(V1);
  257.127 ns (2 allocations: 320 bytes)

julia> V2aoa_view = @btime nestedview(flatview(V1aoa)');
  38.514 ns (2 allocations: 32 bytes)

julia> V2aoa_copy = @btime nestedview(copy(flatview(V1aoa)'));
  103.347 ns (3 allocations: 336 bytes)

```

(Disclaimer: It’s my package 🙂 )
