# Spdiag Matlab function in Julia

**URL:** <https://discourse.julialang.org/t/spdiag-matlab-function-in-julia/39604>\
**Category:** General Usage\
**Created:** [May 16, 2020, 11:12pm UTC](https://discourse.julialang.org/t/spdiag-matlab-function-in-julia/39604 "2020-05-16T23:12:34Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![juliauser](https://avatars.discourse-cdn.com/v4/letter/j/46a35a/32.png) [@juliauser](https://discourse.julialang.org/u/juliauser)\
**Post date:** [May 16, 2020, 11:12pm UTC](https://discourse.julialang.org/t/spdiag-matlab-function-in-julia/39604/1 "2020-05-16T23:12:34Z")

</div>

Is it possible to create an upper triangular matrix in Julia as fast as in Matlab, given the vectors that occupy “diagonal” positions? To be precise, spdiags allows to locate a vector on the diagonal (index=0) or the first diagonal on the right of the matrix diagonal (index=1), this way creating an upper diagonal matrix, and so on and so forth. The only information needed are the vector itself and the position (0,1,2,3,…N-1, -1,-2,-3,…) where negative numbers are positions in a lower triangular matrix. No need to provide the entire vector of indeces!

---

<div class="post-metadata">

**Author:** ![saulo.giovani](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/saulo.giovani/32/15071_2.png) [@saulo.giovani](https://discourse.julialang.org/u/saulo.giovani)\
**Post date:** [May 16, 2020, 11:17pm UTC](https://discourse.julialang.org/t/spdiag-matlab-function-in-julia/39604/2 "2020-05-16T23:17:32Z")

</div>

Yes, you are looking for `spdiagm` in Julia. You need to add `using SparseArrays`. For more information see: [Sparse Arrays · The Julia Language](https://docs.julialang.org/en/v1/stdlib/SparseArrays/#SparseArrays.spdiagm) . Unfortunately, it creates a square matrix, so you need to cut off the lines or columns that you don’t want. Here one example:

```julia
MVtmp = spdiagm(2 => ones(4), 0 => -ones(4));
Matrix(MVtmp)

Output:
6×6 Array{Float64,2}:
 -1.0 0.0 1.0 0.0 0.0 0.0
  0.0 -1.0 0.0 1.0 0.0 0.0
  0.0 0.0 -1.0 0.0 1.0 0.0
  0.0 0.0 0.0 -1.0 0.0 1.0
  0.0 0.0 0.0 0.0 0.0 0.0
  0.0 0.0 0.0 0.0 0.0 0.0

```

but if you want a 4x6 matrix, you need to do:

```julia
MV = MVtmp[1:4,:];
Matrix(MV)

Output:
4×6 Array{Float64,2}:
 -1.0 0.0 1.0 0.0 0.0 0.0
  0.0 -1.0 0.0 1.0 0.0 0.0
  0.0 0.0 -1.0 0.0 1.0 0.0
  0.0 0.0 0.0 -1.0 0.0 1.0

```

I’ve used the function `Matrix()` to visualise the sparse matrix.

---

<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:** [May 17, 2020, 12:32am UTC](https://discourse.julialang.org/t/spdiag-matlab-function-in-julia/39604/3 "2020-05-17T00:32:24Z")

</div>

> [@saulo.giovani](#):
>
> Unfortunately, it creates a square matrix

This was [fixed in Julia 1.3](https://github.com/JuliaLang/julia/pull/31654) — `spdiagm` now allows you to pass optional size arguments to create non-square matrices:

```julia
julia> Matrix(spdiagm(4, 6, 2 => ones(4), 0 => -ones(4)))
4×6 Array{Float64,2}:
 -1.0 0.0 1.0 0.0 0.0 0.0
  0.0 -1.0 0.0 1.0 0.0 0.0
  0.0 0.0 -1.0 0.0 1.0 0.0
  0.0 0.0 0.0 -1.0 0.0 1.0

```

---

<div class="post-metadata">

**Author:** ![juliauser](https://avatars.discourse-cdn.com/v4/letter/j/46a35a/32.png) [@juliauser](https://discourse.julialang.org/u/juliauser)\
**Post date:** [May 17, 2020, 1:53am UTC](https://discourse.julialang.org/t/spdiag-matlab-function-in-julia/39604/4 "2020-05-17T01:53:55Z")

</div>

Wonderful!

---

<div class="post-metadata">

**Author:** ![rguerrab](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rguerrab/32/22134_2.png) [@rguerrab](https://discourse.julialang.org/u/rguerrab)\
**Post date:** [February 19, 2021, 2:55pm UTC](https://discourse.julialang.org/t/spdiag-matlab-function-in-julia/39604/5 "2021-02-19T14:55:39Z")

</div>

What if I want to declare a matrix that’s 1000x1000 with a hundred populated diagonals? spdiags in Matlab can take a dense array that stores the diagonal entries, a vector of offsets, and matrix dimension paramters to build n-diagonal matrix using: A = spdiags(Bin,d,m,n);

Is there a comparable syntax for this?

---

<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 19, 2021, 3:12pm UTC](https://discourse.julialang.org/t/spdiag-matlab-function-in-julia/39604/6 "2021-02-19T15:12:42Z")

</div>

You would call [`spdiagm` from the SparseArrays stdlib](https://docs.julialang.org/en/v1/stdlib/SparseArrays/#SparseArrays.spdiagm), e.g. you can emulate the Matlab syntax `A = spdiags(Bin,d,1000,1000)` with:

```julia
spdiagm(1000,1000, [d[i] => Bin[1:1000-abs(d[i]), i] for i = 1:length(d)]...)

```

Note that Matlab’s `Bin` is a bit odd because Matlab only uses part of each column `Bin[:,i]` depending on the diagonal `d[i]`, whereas Julia expects a vector of the correct length for the corresponding diagonal.

The code is a bit simpler if you have an array of arrays `B`, where each element `B[i]` is a vector (of the correct length) of the entries on diagonal `i`:

```julia
spdiagm(1000,1000, (d .=> B)...)

```

Here, I’m using the [broadcasting “dot” operator](https://docs.julialang.org/en/v1/manual/mathematical-operations/#man-dot-operators) `.=>` version of the pair constructor `=>`.

For example:

```julia
julia> using SparseArrays

julia> d = [7,3,0,-2,-8];

julia> B = [rand(1000 - abs(d)) for d in d];

julia> A = spdiagm(1000,1000, (d .=> B)...)
1000×1000 SparseMatrixCSC{Float64, Int64} with 4980 stored entries:
⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣦⡀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠻⣦

```

(The last output is the new sparse-matrix display format [in Julia 1.6](https://github.com/JuliaLang/julia/pull/33821).)

> [@rguerrab](#):
>
> What if I want to declare a matrix that’s 1000x1000 with a hundred populated diagonals?

You should also look into the [BandedMatrices.jl package](https://github.com/JuliaMatrices/BandedMatrices.jl), which is likely to be _much_ more efficient than generic sparse matrices in this case, especially since your matrix is not particularly sparse (10% sparsity).

---

<div class="post-metadata">

**Author:** ![rguerrab](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rguerrab/32/22134_2.png) [@rguerrab](https://discourse.julialang.org/u/rguerrab)\
**Post date:** [February 19, 2021, 4:40pm UTC](https://discourse.julialang.org/t/spdiag-matlab-function-in-julia/39604/7 "2021-02-19T16:40:48Z")

</div>

I love the `.=>` notation, though splatting still confuses me. I was going to kludge a packed array to `I, J, V` converter, but this is much better. Thanks!

Just for those wanting to translate Matlab code directly, the syntax for your first solution should be:  
`spdiagm(1000,1000, [d[i] => Bin[1+maximum([0,d[i]]):1000+minimum([0,d[i]]), i] for i = 1:length(d)]...)`  
This takes care of the way Matlab wants the zero padding of the packed array to work.

---

<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 19, 2021, 4:45pm UTC](https://discourse.julialang.org/t/spdiag-matlab-function-in-julia/39604/8 "2021-02-19T16:45:08Z")

</div>

> [@rguerrab](#):
>
> `maximum([0,d[i]])`

Better to just do `max(0,d[i])` and `min(0,d[i])`.

(This is a Matlab-ism and Julia anti-pattern — allocating an array of 2 elements just to take the maximum. Matlab (and Numpy and R) really train programmers in a distorted style, unfortunately.)
