# Is there a simple/intuitive way to partition a matrix by arbitrary strides? Like i

**URL:** https://discourse.julialang.org/t/is-there-a-simple-intuitive-way-to-partition-a-matrix-by-arbitrary-strides-like-i/55863
**Category:** General Usage
**Tags:** matrices
**Created:** [February 23, 2021, 4:57pm UTC](https://discourse.julialang.org/t/is-there-a-simple-intuitive-way-to-partition-a-matrix-by-arbitrary-strides-like-i/55863 "2021-02-23T16:57:12Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![BridgeBot](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bridgebot/32/21491_2.png) [@BridgeBot](https://discourse.julialang.org/u/BridgeBot)
#### Post date: [February 23, 2021, 4:57pm UTC](https://discourse.julialang.org/t/is-there-a-simple-intuitive-way-to-partition-a-matrix-by-arbitrary-strides-like-i/55863/1 "2021-02-23T16:57:12Z")

</div>

Is there a simple/intuitive way to partition a matrix by arbitrary strides? Like if I had a 20 x 5 matrix and wanted the output to be a vector/iterable of 10x5, 3x5, 4x5, 3x5 ? Essentially, the “split” part of split-apply-combine, but for a matrix, and based on partition size.  
Theoretically:

```julia
foo(rand(20,5), [10,3,4,3])

```

Note that the original poster on Slack cannot see your response here on Discourse. Consider _transcribing the appropriate answer back to Slack_, or pinging the poster here on Discourse so they can _follow this thread_.  
[(Original message :slack:)](https://julialang.slack.com/archives/C6A044SQH/p1614099046207700?thread_ts=1614099046.207700&cid=C6A044SQH) [(More Info)](https://github.com/JuliaCommunity/SlackBridge)

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [February 23, 2021, 5:06pm UTC](https://discourse.julialang.org/t/is-there-a-simple-intuitive-way-to-partition-a-matrix-by-arbitrary-strides-like-i/55863/2 "2021-02-23T17:06:40Z")

</div>

```julia
@views function splititerator(M::AbstractMatrix, rowlens::AbstractVector{<:Integer})
    sum(rowlens) <= size(M,1) || throw(DimensionMismatch())
    let s = cumsum([first(axes(M,1)); rowlens])
        return (M[s[i]:s[i+1]-1,:] for i = 1:length(s)-1)
    end
end

```

---

<div class="post-metadata">

### Author: ![pdimens](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdimens/32/15729_2.png) [@pdimens](https://discourse.julialang.org/u/pdimens)
#### Post date: [February 23, 2021, 5:13pm UTC](https://discourse.julialang.org/t/is-there-a-simple-intuitive-way-to-partition-a-matrix-by-arbitrary-strides-like-i/55863/3 "2021-02-23T17:13:33Z")

</div>

Answer on Slack provided by @mcabbott

```julia
julia> function foo(mat, sizes)
       axes(mat,1) == 1:sum(sizes) || error("bad sizes!")
       z = 0
       map(sizes) do s
         r = z+1:z+s
         z = s
         mat[r,:]
       end
       end;
julia> foo(rand(20,5), [10,3,4,3]) .|> size
4-element Vector{Tuple{Int64, Int64}}:
 (10, 5)
 (3, 5)
 (4, 5)
 (3, 5)

```

---

<div class="post-metadata">

### Author: ![pdimens](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdimens/32/15729_2.png) [@pdimens](https://discourse.julialang.org/u/pdimens)
#### Post date: [February 23, 2021, 5:31pm UTC](https://discourse.julialang.org/t/is-there-a-simple-intuitive-way-to-partition-a-matrix-by-arbitrary-strides-like-i/55863/4 "2021-02-23T17:31:20Z")

</div>

Second, faster answer provided by @mcabbott on Slack:

```julia
foo(mat, sizes::Tuple{}) = ()

@views function foo(mat, sizes::Tuple) 
    (mat[1:first(sizes),:], foo(mat[first(sizes)+1:end,:], Base.tail(sizes))...);
end

julia> foo(rand(20,5), (10,3,4,3)) .|> size
((10, 5), (3, 5), (4, 5), (3, 5))

```

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [February 23, 2021, 6:20pm UTC](https://discourse.julialang.org/t/is-there-a-simple-intuitive-way-to-partition-a-matrix-by-arbitrary-strides-like-i/55863/5 "2021-02-23T18:20:33Z")

</div>

> [@pdimens](#):
>
> Second, faster answer

Small, fixed-size tuples are fast (along with code like that will unroll at compile-time). On the other hand, if you have a list of hundreds of sizes, whose length is determined at runtime, using tuples is likely to be slower.

In this case, because you are talking about an list or generator of submatrices, where the limiting factor in performance is likely to be the subsequent matrix operations rather than generating the list, I wouldn’t tend to recommend tuple tricks — go for code simplicity instead.

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [February 23, 2021, 6:31pm UTC](https://discourse.julialang.org/t/is-there-a-simple-intuitive-way-to-partition-a-matrix-by-arbitrary-strides-like-i/55863/6 "2021-02-23T18:31:49Z")

</div>

As I mentioned in the slack thread, I’d split the problem. First create a function that splits a vector (or likely any iterator) into parts the way you’d like. Then use that to create your more complicated row splitting. For example, we have a builtin iterator that gives you splits of a constant size:

```julia
(@views(A[I, :]) for I in Iterators.partition(axes(A, 1), 4))

```

It’s much more composable this way.

---

<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: [February 23, 2021, 7:38pm UTC](https://discourse.julialang.org/t/is-there-a-simple-intuitive-way-to-partition-a-matrix-by-arbitrary-strides-like-i/55863/7 "2021-02-23T19:38:45Z")

</div>

@mbauman, trying to follow your illuminating advice. Could you kindly comment on Julia-novice code below. Thanks in advance.

```julia
function splititr(b)
    c = cumsum([1;b])
    return [ci:ci+bi-1 for (ci,bi) in zip(c,b)]
end

split_mbauman(M,I0) = (@views(M[I, :]) for I in I0)

M = rand(20,5)
b = [10,3,4,3]
it = splititr(b)
R = collect(split_mbauman(M,it))
# splits in R[1], R[2], ... R[4]

```

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [February 23, 2021, 8:32pm UTC](https://discourse.julialang.org/t/is-there-a-simple-intuitive-way-to-partition-a-matrix-by-arbitrary-strides-like-i/55863/8 "2021-02-23T20:32:18Z")

</div>

Yeah, you could really use any of the above implementations for creating the splits — the idea is just to detangle the splitting of a 1-dimensional iterable/vector from the indexing into the matrix. It makes it easier to test and easier to use in different situations.

---

<div class="post-metadata">

### Author: ![pdimens](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdimens/32/15729_2.png) [@pdimens](https://discourse.julialang.org/u/pdimens)
#### Post date: [February 24, 2021, 5:50am UTC](https://discourse.julialang.org/t/is-there-a-simple-intuitive-way-to-partition-a-matrix-by-arbitrary-strides-like-i/55863/9 "2021-02-24T05:50:32Z")

</div>

@mcabbott also suggested this, which is similar to the proposed solution by @rafael.guerra :

```julia
function steps(vals, steps)
    i = firstindex(vals)
    (view(vals, i:(i+=s)-1) for s in steps)
end

mat = rand(20,2)
batches = steps(axes(mat,1), [10,3,4,3])

[view(mat,r,:) for r in batches]

```

Is this functionality (in general) something that can be a PR for `Base.Iterators` ?

---

<div class="post-metadata">

### Author: ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)
#### Post date: [February 24, 2021, 3:26pm UTC](https://discourse.julialang.org/t/is-there-a-simple-intuitive-way-to-partition-a-matrix-by-arbitrary-strides-like-i/55863/10 "2021-02-24T15:26:12Z")

</div>

The part that could potentially go into `Iterators` would be the 1-dimensional version. It’d be fairly complicated because it’d have to work on arbitrary iterators, but I’d also want it to have the fancy precomputing stuff for splitting ranges like `Iterators.partition` does.
