0

I know about np.eye which generates identity matrix. This question is about the algorithm rather than about the final result.

In Q (kdb+ language) I can generate identity matrix using the following code:

`float${x =\: x} til 12000

Python numpy equivalent is more or less this:

import numpy as np
r=np.arange(12000)
np.asarray([i==r for i in r]).astype(float)

With Python approach there's an unnecessary data copying during np.asarray to convert Python array back into numpy array. Is there a way to avoid this copying? I.e. I want to perform [i==r for i in r] without getting out of numpy domain.

Konstantin Spirin
  • 20,609
  • 15
  • 72
  • 90

2 Answers2

2
In [822]: r=np.arange(4)

Your list comprehension:

In [823]: [i==r for i in r]
Out[823]: 
[array([ True, False, False, False]),
 array([False,  True, False, False]),
 array([False, False,  True, False]),
 array([False, False, False,  True])]

A broadcasted array equivalent:

In [824]: r[:,None]==r[None,:]
Out[824]: 
array([[ True, False, False, False],
       [False,  True, False, False],
       [False, False,  True, False],
       [False, False, False,  True]])

another array approach:

In [825]: A = np.zeros((4,4),int)
In [826]: A[np.arange(4),np.arange(4)] = 1
In [827]: A
Out[827]: 
array([[1, 0, 0, 0],
       [0, 1, 0, 0],
       [0, 0, 1, 0],
       [0, 0, 0, 1]])

or (inspired by the code for np.tri):

In [831]: np.equal.outer(np.arange(4), np.arange(4))
Out[831]: 
array([[ True, False, False, False],
       [False,  True, False, False],
       [False, False,  True, False],
       [False, False, False,  True]])
hpaulj
  • 221,503
  • 14
  • 230
  • 353
1

If your goal is to generate the unit matrix in the most efficient way, I would recommend the following trick:

>>> n = 5
>>> e = np.zeros(n*n)
>>> e[::n+1] = 1
>>> e.reshape((n, n))
array([[1., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0.],
       [0., 0., 1., 0., 0.],
       [0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 1.]])
Alexander Belopolsky
  • 2,228
  • 10
  • 26