# Optimal way to do in-place modification of sparse matrix?

**URL:** <https://discourse.julialang.org/t/optimal-way-to-do-in-place-modification-of-sparse-matrix/5170>\
**Category:** General Usage\
**Created:** [August 1, 2017, 6:37pm UTC](https://discourse.julialang.org/t/optimal-way-to-do-in-place-modification-of-sparse-matrix/5170 "2017-08-01T18:37:49Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [August 1, 2017, 6:37pm UTC](https://discourse.julialang.org/t/optimal-way-to-do-in-place-modification-of-sparse-matrix/5170/1 "2017-08-01T18:37:49Z")

</div>

I’m looking for the most performant way to modify a large `SparseMatrixCSC` in-place. The matrix is initially built using the `sp = sparse(I,J,K)` method. Later, I need to modify only the non-zero entries in `sp`. I’m tempted to do

```julia
sp.nzval .= newK

```

where `newK` is the updated `K` vector. This is really fast, but I worry this approach is fragile (as e.g. there are no guarantees that zeros in the original K are dropped when building the original `sp`, or that the order of `sp.nzval` is the same as in `K`). Can this be made safe? If not, is there some recommended approach with comparable performance?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [August 1, 2017, 7:13pm UTC](https://discourse.julialang.org/t/optimal-way-to-do-in-place-modification-of-sparse-matrix/5170/2 "2017-08-01T19:13:01Z")

</div>

There is `dropzeros!` to remove all the stored zeros.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [August 1, 2017, 8:08pm UTC](https://discourse.julialang.org/t/optimal-way-to-do-in-place-modification-of-sparse-matrix/5170/3 "2017-08-01T20:08:03Z")

</div>

Hi Kristoffer!  
I know about `dropzeros!`, but my problem is the opposite. I want to _keep_ some structural zeroes when building `sp`, as they may become non-zero when updating it. Moreover, to use `sp.nzval .= newK` safely, I need to be sure about the order of `sp.nzval`, so I know which entry in the matrix I’m modifying for each element of `newK`. I have the feeling, however, that this is just not the proper Julian way to do what I want, hence the question.

I see roughly three possible approaches to modify structural values of `sp` after the fact

1- In-place `broadcast!` directly over `sp.nzval` (risky!)

```julia
julia> @btime sp.nzval .= newK;
  5.358 μs (0 allocations: 0 bytes)

```

2- In-place `setindex!` over structural values

```julia
julia> updatesp!(sp, I, J, newK) = for (k,(i,j)) in enumerate(zip(I, J)); sp[i,j] = newK[k]; end
updatesp! (generic function with 1 method)

julia> @btime updatesp!(sp, I, J, newK)
  154.394 μs (0 allocations: 0 bytes)

```

3- Allocating a whole new sparse matrix

```julia
julia> @btime sparse(I, J, newK);
  334.870 μs (19 allocations: 547.78 KiB)

```

I like the speed of 1 🙂. The question is whether it is possible to do something that is “safe” with comparable performance.

EDIT: corrected typo in code.

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [August 2, 2017, 1:08pm UTC](https://discourse.julialang.org/t/optimal-way-to-do-in-place-modification-of-sparse-matrix/5170/4 "2017-08-02T13:08:48Z")

</div>

> [@pablosanjose](#):
>
> as e.g. there are no guarantees that zeros in the original K are dropped when building the original sp, or that the order of sp.nzval is the same as in K)

In the docs for `sparse` (Julia 0.6) it says: “Numerical zeros in (I, J, V) are retained as structural nonzeros; to drop numerical zeros, use dropzeros!.”. So your `sp.nzval .= newK` is fine.

---

<div class="post-metadata">

**Author:** ![pablosanjose](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pablosanjose/32/7006_2.png) [@pablosanjose](https://discourse.julialang.org/u/pablosanjose)\
**Post date:** [August 2, 2017, 3:59pm UTC](https://discourse.julialang.org/t/optimal-way-to-do-in-place-modification-of-sparse-matrix/5170/5 "2017-08-02T15:59:42Z")

</div>

Ah, great. So there _is_ a guarantee that structural zeros are not dropped. On the other hand I only now realised that the order of `sp.nzval` is also guaranteed to sweep columns of `sp` in order, so the `sp.nzval .= newK` is indeed safe. Thanks a lot!
