5

Sometimes is useful to assign arrays with one index only. In Matlab this is straightforward:

M = zeros(4);
M(1:5:end) = 1
M =

   1   0   0   0
   0   1   0   0
   0   0   1   0
   0   0   0   1

Is there a way to do this in Numpy? First I thought to flatten the array, but that operation doesn't preserve the reference, as it makes a copy. I tried with ix_ but I couldn't manage to do it with a relatively simple syntax.

3
  • 1
    this was discussed before here: stackoverflow.com/questions/3257619/… and here: stackoverflow.com/questions/15230179/… Commented Dec 19, 2013 at 18:27
  • 1
    Hmm, they both don't seem to mention the arr.flat attribute. Commented Dec 19, 2013 at 18:33
  • 3
    I like this question better than the other two. It concisely brings the problem to the point. Commented Dec 19, 2013 at 18:44

3 Answers 3

8

You could try numpy.ndarray.flat, which represents an iterator that you can use for reading and writing into the array.

>>> M = zeros((4,4))
>>> M.flat[::5] = 1
>>> print(M)
array([[ 1.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]])

Note that in numpy the slicing syntax is [start:stop_exclusive:step], as opposed to Matlab's (start:step:stop_inclusive).

Based on sebergs comment it might be important to point out that Matlab stores matrices in column major, while numpy arrays are row major by default.

>>> M = zeros((4,4))
>>> M.flat[:4] = 1
>>> print(M)
array([[ 1.,  1.,  1.,  1.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.]])

To get Matlab-like indexing on the flattened array you will need to flatten the transposed array:

>>> M = zeros((4,4))
>>> M.T.flat[:4] = 1
>>> print(M)
array([[ 1.,  0.,  0.,  0.],
       [ 1.,  0.,  0.,  0.],
       [ 1.,  0.,  0.,  0.],
       [ 1.,  0.,  0.,  0.]])
Sign up to request clarification or add additional context in comments.

2 Comments

numpy is C, not fortran order though, it is not quite the same.
Indeed. I have edited the answer to point out that difference.
2

You could do this using list indices:

M = np.zeros((4,4))
M[range(4), range(4)] = 1
print M
# [[ 1.  0.  0.  0.]
#  [ 0.  1.  0.  0.]
#  [ 0.  0.  1.  0.]
#  [ 0.  0.  0.  1.]]

In this case you could also use np.identity(4)

2 Comments

There is also a function made specifically for this.
The example of a diagonal assignation, was just an example. I was asking how to use the more or less the same syntax that is used in matlab
1

Another way using unravel_index

>>> M = zeros((4,4));
>>> M[unravel_index(arange(0,4*4,5),(4,4))]= 1
>>> M
array([[ 1.,  0.,  0.,  0.],
       [ 0.,  1.,  0.,  0.],
       [ 0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  1.]])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.