# How to extract sub-matrices (or their indexes) of Block Diagonal Matrix?

**URL:** <https://discourse.julialang.org/t/how-to-extract-sub-matrices-or-their-indexes-of-block-diagonal-matrix/88188>\
**Category:** General Usage\
**Tags:** question\
**Created:** [October 3, 2022, 8:42pm UTC](https://discourse.julialang.org/t/how-to-extract-sub-matrices-or-their-indexes-of-block-diagonal-matrix/88188 "2022-10-03T20:42:03Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Amro](https://avatars.discourse-cdn.com/v4/letter/a/4491bb/32.png) [@Amro](https://discourse.julialang.org/u/Amro)\
**Post date:** [October 3, 2022, 8:42pm UTC](https://discourse.julialang.org/t/how-to-extract-sub-matrices-or-their-indexes-of-block-diagonal-matrix/88188/1 "2022-10-03T20:42:03Z")

</div>

Is there a function in Julia to return(extract) the sub-matrices (or their indexes) from Block Diagonal Matrix similar to here [Extract matrices from a Block Diagonal Matrix?](https://stackoverflow.com/questions/10831417/extracting-diagonal-blocks-from-a-numpy-array)?  
For example, I need to return `A[1:3,1:3]`, `A[4:5,4:5]`, and `A[6:end,6:end] i.e., or indexes of (3,3) and (5,5).

```julia
julia> A = sparse([5.0 1 2 0 0 0 0; 2 1 5 0 0 0 0; 5 6 7 0 0 0 0; 0 0 0 2 -1 0 0; 0 0 0 5 6 0 0; 0 0 0 0 0 10 11; 0 0 0 0 0 2 3])
7×7 SparseMatrixCSC{Float64, Int64} with 17 stored entries:
 5.0 1.0 2.0 ⋅ ⋅ ⋅ ⋅
 2.0 1.0 5.0 ⋅ ⋅ ⋅ ⋅
 5.0 6.0 7.0 ⋅ ⋅ ⋅ ⋅
  ⋅ ⋅ ⋅ 2.0 -1.0 ⋅ ⋅ 
  ⋅ ⋅ ⋅ 5.0 6.0 ⋅ ⋅
  ⋅ ⋅ ⋅ ⋅ ⋅ 10.0 11.0
  ⋅ ⋅ ⋅ ⋅ ⋅ 2.0 3.0

```

---

<div class="post-metadata">

**Author:** ![Amro](https://avatars.discourse-cdn.com/v4/letter/a/4491bb/32.png) [@Amro](https://discourse.julialang.org/u/Amro)\
**Post date:** [October 4, 2022, 12:28pm UTC](https://discourse.julialang.org/t/how-to-extract-sub-matrices-or-their-indexes-of-block-diagonal-matrix/88188/2 "2022-10-04T12:28:36Z")

</div>

Please, any comment here?

---

<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:** [October 4, 2022, 1:02pm UTC](https://discourse.julialang.org/t/how-to-extract-sub-matrices-or-their-indexes-of-block-diagonal-matrix/88188/3 "2022-10-04T13:02:54Z")

</div>

I don’t know of any built-in function to extract the locations of the diagonal blocks, but you could always write your own, e.g. here is something simple (that assumes `A` is block-diagonal):

```julia
using SparseArrays, LinearAlgebra
function diagblocks(A::SparseArrays.AbstractSparseMatrixCSC)
    m = LinearAlgebra.checksquare(A)
    rows = rowvals(A)
    blocks = Matrix{eltype(A)}[]
    prevj = 1 # index of previous block's first column
    for j = 1:m
        if j > prevj && rows[first(nzrange(A, j))] >= j # new block starting
            push!(blocks, Matrix(@view A[prevj:j-1, prevj:j-1]))
            prevj = j
        end
    end
    push!(blocks, Matrix(@view A[prevj:m, prevj:m])) # last block
    return blocks
end

```

which gives:

```julia
julia> display.(diagblocks(A));
3×3 Matrix{Float64}:
 5.0 1.0 2.0
 2.0 1.0 5.0
 5.0 6.0 7.0
2×2 Matrix{Float64}:
 2.0 -1.0
 5.0 6.0
2×2 Matrix{Float64}:
 10.0 11.0
  2.0 3.0

```

for your matrix.

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [October 4, 2022, 1:15pm UTC](https://discourse.julialang.org/t/how-to-extract-sub-matrices-or-their-indexes-of-block-diagonal-matrix/88188/4 "2022-10-04T13:15:42Z")

</div>

If you know the sizes of the blocks, you may use existing packages to simplify your code:

```julia
julia> using BlockArrays, LinearAlgebra

julia> B = BlockMatrix(A, [3,2,2], [3,2,2]);

julia> diag(blocks(B))
3-element Vector{SparseMatrixCSC{Float64, Int64}}:
 sparse([1, 2, 3, 1, 2, 3, 1, 2, 3], [1, 1, 1, 2, 2, 2, 3, 3, 3], [5.0, 2.0, 5.0, 1.0, 1.0, 6.0, 2.0, 5.0, 7.0], 3, 3)
 sparse([1, 2, 1, 2], [1, 1, 2, 2], [2.0, 5.0, -1.0, 6.0], 2, 2)
 sparse([1, 2, 1, 2], [1, 1, 2, 2], [10.0, 2.0, 11.0, 3.0], 2, 2)

```

---

<div class="post-metadata">

**Author:** ![Amro](https://avatars.discourse-cdn.com/v4/letter/a/4491bb/32.png) [@Amro](https://discourse.julialang.org/u/Amro)\
**Post date:** [October 4, 2022, 1:15pm UTC](https://discourse.julialang.org/t/how-to-extract-sub-matrices-or-their-indexes-of-block-diagonal-matrix/88188/5 "2022-10-04T13:15:54Z")

</div>

Got it, thank you very much

---

<div class="post-metadata">

**Author:** ![Amro](https://avatars.discourse-cdn.com/v4/letter/a/4491bb/32.png) [@Amro](https://discourse.julialang.org/u/Amro)\
**Post date:** [October 4, 2022, 1:17pm UTC](https://discourse.julialang.org/t/how-to-extract-sub-matrices-or-their-indexes-of-block-diagonal-matrix/88188/6 "2022-10-04T13:17:53Z")

</div>

Thanks for your comment.  
Actually, I am assuming that I dont know the sizes in advance.
