Reputation: 1029
I guess I'm having a slow day and can't figure this one out. I have an m x n numpy array and want to convert it to a vector where each element is a 3 dimensional vector containing the row number, column number and value of all the elements in the array.
For example, given an numpy array, a, the first element in the vector would be: [1, 1, a[1, 1]] then the next would be [1, 2, a[1, 2]] etc.
Upvotes: 1
Views: 1248
Reputation: 231738
This sequence produces a (3, n*m) array with the indices and values
In [786]: A = np.arange(12).reshape(3,4)
In [787]: X=np.vstack([np.indices(A.shape),A[None,...]]).reshape(3,-1)
In [788]: X.shape
Out[788]: (3, 12)
In [789]: X
Out[789]:
array([[ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2],
[ 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3],
[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]])
It can be transposed to make each 'row' represent an element:
In [793]: X.T[0,:]
Out[793]: array([0, 0, 0])
In [794]: X.T[10,:]
Out[794]: array([ 2, 2, 10])
It could also be cast into a structured array with length (n*m,)
, and dtype('i4,i4,i4')
. This example is a bit messy, but it does job:
In [796]: dt=np.dtype('i4,i4,i4')
In [806]: X1=np.zeros(X.shape[1],dtype=dt)
In [809]: X1['f0']=X[0]
In [810]: X1['f1']=X[1]
In [811]: X1['f2']=X[2]
# or more compactly: for i,n in enumerate(X1.dtype.names): X1[n] = X[i,:]
In [812]: X1
Out[812]:
array([(0, 0, 0), (0, 1, 1), (0, 2, 2), (0, 3, 3), (1, 0, 4), (1, 1, 5),
(1, 2, 6), (1, 3, 7), (2, 0, 8), (2, 1, 9), (2, 2, 10), (2, 3, 11)],
dtype=[('f0', '<i4'), ('f1', '<i4'), ('f2', '<i4')])
In [813]: X1[10]
Out[813]: (2, 2, 10) # note, this a tuple
In [814]: X1['f2']
Out[814]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
Lets say the original matrix is floats, and we want to preserve that type in the new array. We could do that by skipping the vstack
step:
In [833]: A = np.arange(12,dtype=float).reshape(3,4)
In [834]: X = np.indices(A.shape).reshape(2,-1)
...
In [848]: dt=np.dtype([('row',int), ('col',int), ('value',float)])
In [850]: X1 = np.zeros(X.shape[1], dtype=dt)
In [851]: X1['row']=X[0,:]
In [852]: X1['col']=X[1,:]
In [853]: X1['value']=A.flatten()
In [854]: X1
Out[854]:
array([(0, 0, 0.0), (0, 1, 1.0), (0, 2, 2.0), (0, 3, 3.0), (1, 0, 4.0),
(1, 1, 5.0), (1, 2, 6.0), (1, 3, 7.0), (2, 0, 8.0), (2, 1, 9.0),
(2, 2, 10.0), (2, 3, 11.0)],
dtype=[('row', '<i4'), ('col', '<i4'), ('value', '<f8')])
In [855]: X1[10]
Out[855]: (2, 2, 10.0)
X1[10]
is a 0D
array with dtype dt
, and shape ()
, which prints as a tuple.
Upvotes: 1
Reputation: 724
I think something like this should work:
n = 10
m = 5
data = np.random.randn(n, m)
grid = np.indices(data.shape)
r = np.array([grid[0], grid[1], data])
result = np.array(zip(*r.T))
There are probably more efficient ways to do this though. See: numpy.indices
Upvotes: 1