How to assign the diagonal elements of part of matrix to a value?

I know that diagind() returns the index of the diagonal elements of matrix, in which we can assign them to a specific value such as in the below

aa=rand(9,9);
aa[diagind(aa)] .= 1

However, lets say I am working on a part of the matrix aa such as aa[5:7,5:7] and I want to assign its diagonal elements to 1 (in other words aa[5,5]=1, aa[6,6]=1, aa[7,7]=1), how can I do that?

You can simply do:

aa[diagind(aa)[5:7]] .= 1
3 Likes

Thank you very much!
@Seif_Shebl
How is about changing the diagonal elements of aa[5:7,4:6] (i.e., aa[5,4]=1, aa[6,5]=1, aa[7,6]=1)
I tried aa[diagind(aa)[5:7,4:6]] .= 1 but it gives an error

ERROR: BoundsError: attempt to access 9-element StepRange{Int64, Int64} at index [5:7, 5:7]
Stacktrace:

Not very elegant but you could do a comprehension:

  [aa[ind...] = 1 for ind in zip(5:7,4:6)]

It could be very clearly (and with better performance) written with a for loop as well.

Never use a comprehension when you just want a for loop. A comprehension generates an array, so if you don’t want this array it is a pointless side effect, and it’s not any less compact to write for ind in zip(5:7,4:6); aa[ind...] = 1; end or for j in 4:6; aa[j+1,j] = 1; end

3 Likes

Thanks for noting it!

diagind takes an extra argument, so you could write

jl> aa[diagind(aa, -1)[4:6]] .= 1
2 Likes

@DNF Great
How is about
How is about changing the diagonal elements of aa[1:3,4:6] (i.e., aa[1,4]=1, aa[2,5]=1, aa[3,6]=1)

jl> aa[diagind(aa,3)[1:3]] .= 1;

Various combinations of this is possible. Just try some things.

Another approach is to use an extra step involving a view:

jl> av = view(aa, 5:7, 4:6);

jl> av[diagind(av)] .= 1;

And then you could take more general and interesting slices as well, like

jl> av = @view aa[1:2:end, end:-2:1];

jl> av[diagind(av)] .= 1;

jl> aa
10×10 Matrix{Int64}:
 0  0  0  0  0  0  0  0  0  1
 0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  1  0  0
 0  0  0  0  0  0  0  0  0  0
 0  0  0  0  0  1  0  0  0  0
 0  0  0  0  0  0  0  0  0  0
 0  0  0  1  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0
 0  1  0  0  0  0  0  0  0  0
 0  0  0  0  0  0  0  0  0  0
2 Likes

For speed, you should probably use a loop.

@DNF Yes, actually the speed is critical in my situation

Then you should try both and benchmark. Sometimes, the simple high-level versions are competitive.

1 Like