How to make matrix using column matrix? - python

I wanna know how to make a matrix using the column matrix.
For example, I have a [1,2,3] column matrix.
I wanna make the matrix
[ 1 0 0
2 1 0
3 2 1
0 3 2
0 0 3 ]
like this.
So How can I make it? Is there some module to make this matrix in python?

Try using numpy and np.zeros
import numpy as np
def get_matrix(col):
mat = np.zeros((len(col) * 2 - 1, len(col)))
for i in range(len(col)):
mat[i : i + len(col), i] = col
return mat
col = [1, 2, 3]
print(get_matrix(col))
prints:
array([[1., 0., 0.],
[2., 1., 0.],
[3., 2., 1.],
[0., 3., 2.],
[0., 0., 3.]])
and
col = [1, 2, 3, 4, 5]
print(get_matrix(col))
prints
array([[1., 0., 0., 0., 0.],
[2., 1., 0., 0., 0.],
[3., 2., 1., 0., 0.],
[4., 3., 2., 1., 0.],
[5., 4., 3., 2., 1.],
[0., 5., 4., 3., 2.],
[0., 0., 5., 4., 3.],
[0., 0., 0., 5., 4.],
[0., 0., 0., 0., 5.]])
as expected I believe. Otherwise give more precision about how you build your matrix.
Also there may be a smarter (more efficient?) way to do this using pure numpy but I believe this loop is quite readable and not so inefficient

You can use this method to obtain the answer.
import numpy as np
a=[1,2,3]
a.extend([0]*2)
d=[np.roll(a,i) for i in range(3)]
print(d)
[array([1, 2, 3, 0, 0]), array([0, 1, 2, 3, 0]), array([0, 0, 1, 2, 3])]

Related

How to interpret numpy advanced indexing solution

I have a piece of numpy code that I know works. I know this because I have tested it in my generic case successfully. However, I arrived at the solution after two hours of back and forth referencing the docs and trial and error. I can't grasp how I would know to do this intuitively.
The setup:
a = np.zeros((5,5,3))
The goal: Set to 1 indices 0,1 of axis 1, 0,1 of axis 2, all of axis 3 and indices 3,4 of axis 1, 3,4 of axis 2, all of axis 3
Clearer goal: Set block 1 and 2's first two rows to 1 and block 3 and 4's last two rows to 1
The result:
ax1 =np.array([np.array([0,1]),np.array([3,4])])
ax1 =np.array([x[:,np.newaxis] for x in ax1])
ax2 = np.array([[[0,1]],[[3,4]]])
a[ax1,ax2,:] = 1
a
Output:
array([[[1., 1., 1.],
[1., 1., 1.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[1., 1., 1.],
[1., 1., 1.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[1., 1., 1.],
[1., 1., 1.]],
[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[1., 1., 1.],
[1., 1., 1.]]])
I'm inclined to believe I should be able to look at the shape of the matrix in question, the shape of the indices, and the index operation to intuitively know the output. However, I can't put the story together in my head. Like, what's the final shape of the subspace it is altering? How would you explain how this works?
The shapes:
input: (5, 5, 3)
ind1: (2, 2, 1)
ind2: (2, 1, 2)
final_op: input[ind1, ind2, :]
With shapes
ind1: (2, 2, 1)
ind2: (2, 1, 2)
they broadcast together to select a (2,2,2) space
In [4]: ax1
Out[4]:
array([[[0],
[1]],
[[3],
[4]]])
In [5]: ax2
Out[5]:
array([[[0, 1]],
[[3, 4]]])
So for the 1st dimension (blocks) it is selecting blocks 0,1,3,and 4. In the second dimension it is also selecting these rows.
Together that's the first 2 rows of the first 2 blocks, and the last 2 rows of the last 2 blocks. That's where the 1s appear in your result.
A simpler way of creating the index arrays:
In [7]: np.array([[0,1],[3,4]])[:,:,None] # (2,2) expanded to (2,2,1)
In [8]: np.array([[0,1],[3,4]])[:,None,:] # expand to (2,1,2)
This is how broadcasting expands them:
In [10]: np.broadcast_arrays(ax1,ax2)
Out[10]:
[array([[[0, 0], # block indices
[1, 1]],
[[3, 3],
[4, 4]]]),
array([[[0, 1], # row indices
[0, 1]],
[[3, 4],
[3, 4]]])]
This may make the pattern clearer:
In [15]: a[ax1,ax2,:] = np.arange(1,5).reshape(2,2,1)
In [16]: a[:,:,0]
Out[16]:
array([[1., 2., 0., 0., 0.],
[3., 4., 0., 0., 0.],
[0., 0., 0., 0., 0.],
[0., 0., 0., 1., 2.],
[0., 0., 0., 3., 4.]])

Index into NumPy array ignoring NaNs in the indexing array

I have an array of zeros
arr = np.zeros([5,5])
array([[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.]])
I want to assign values based on index so I did this .
out = np.array([[nan,2.,4.,1.,1.],[nan,3.,4.,4.,4.]])
arr[out[0].astype(int),np.arange(len(out[0]))] = 1
arr[out[1].astype(int),np.arange(len(out[1]))] = 1
Assignment works fine if there is 0 instead of nan.
How can I skip assignment in case of nan? and Is it possible to assign values at once from a multidimensional index array rather than using for loop ?
Mask it -
mask = ~np.isnan(out)
arr[out[0,mask[0]].astype(int),np.flatnonzero(mask[0])] = 1
arr[out[1,mask[1]].astype(int),np.flatnonzero(mask[1])] = 1
Sample run -
In [171]: out
Out[171]:
array([[ nan, 2., 4., 1., 1.],
[ nan, 3., 4., 4., 4.]])
In [172]: mask = ~np.isnan(out)
...: arr[out[0,mask[0]].astype(int),np.flatnonzero(mask[0])] = 1
...: arr[out[1,mask[1]].astype(int),np.flatnonzero(mask[1])] = 1
...:
In [173]: arr
Out[173]:
array([[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 1., 1.],
[ 0., 1., 0., 0., 0.],
[ 0., 1., 0., 0., 0.],
[ 0., 0., 1., 1., 1.]])
Alternative, replace the flatnonzero calls with range-masking -
r = np.arange(arr.shape[1])
arr[out[0,mask[0]].astype(int),r[mask[0]]] = 1
arr[out[1,mask[1]].astype(int),r[mask[1]]] = 1
If you are working with a lot many rows than just 2 and you want to assign them in a vectorized manner, here's one method, using linear-indexing -
n = arr.shape[1]
linear_idx = (out*n + np.arange(n))
np.put(arr, linear_idx[~np.isnan(linear_idx)].astype(int), 1)

How to fill numpy array of zeros with ones given indices/coordinates

Given a numpy array of zeros, say
arr = np.zeros((5, 5))
and an array of indices that represent vertices of a polygon, say
verts = np.array([[0, 2], [2, 0], [2, 4]])
1) What is the elegant way of doing
for v in verts:
arr[v[0], v[1]] = 1
such that the resulting array is
In [108]: arr
Out[108]:
array([[ 0., 0., 1., 0., 0.],
[ 0., 0., 0., 0., 0.],
[ 1., 0., 0., 0., 1.],
[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.]])
2) How can I fill the array with ones such that the output array is
In [158]: arr
Out[158]:
array([[ 0., 0., 1., 0., 0.],
[ 0., 1., 1., 1., 0.],
[ 1., 1., 1., 1., 1.],
[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.]])
To answer the first part of your question: arr[tuple(verts.T)] = 1
verts.T transposes your indices to a (2, n) array, where the two rows correspond to the row and column dimensions of arr. These are then unpacked into a tuple of (row_indices, col_indices), which we then use to index into arr.
We could write this a bit more verbosely as:
row_indices = verts[:, 0]
col_indices = verts[:, 1]
arr[row_indices, col_indices] = 1
For the second part, one method that will work for arbitrary polygons would be to use matplotlib.Path.contains_points, as described here:
from matplotlib.path import Path
points = np.indices(arr.shape).reshape(2, -1).T
path = Path(verts)
mask = path.contains_points(points, radius=1e-9)
mask = mask.reshape(arr.shape).astype(arr.dtype)
print(repr(mask))
# array([[ 0., 0., 1., 0., 0.],
# [ 0., 1., 1., 1., 0.],
# [ 1., 1., 1., 1., 1.],
# [ 0., 0., 0., 0., 0.],
# [ 0., 0., 0., 0., 0.]])

Create a Numpy array representing connections in a network

Say I have an array describing network links between nodes:
array([[ 1., 2.],
[ 2., 3.],
[ 3., 4.]])
This would be a linear 4 node network with links from node 1 to node 2 and so on..
What would be the best way to convert this information to an array of the following format?
array([[ 0., 1., 0., 0.],
[ 0., 0., 1., 0.],
[ 0., 0., 0., 1.],
[ 0., 0., 0., 0.]])
The column numbers then represent the "to nodes" and the rows the "from nodes".
Another example would be:
array([[ 1., 2.],
[ 2., 3.],
[ 2., 4.]])
giving
array([[ 0., 1., 0., 0.],
[ 0., 0., 1., 1.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]])
Node ids should be integers. Also the rows and columns in numpy are numbered from zero, so we have to substract one in each dimension:
import numpy as np
conns = np.array([[ 1, 2],
[ 2, 3],
[ 3, 4]])
net = np.zeros((conns.max(), conns.max()), dtype=int)
# two possibilities:
# if you need the number of connections:
for conn in conns:
net[conn[0]-1, conn[1]-1] += 1
# if you just need a 1 for existing connection(s):
net[conns[:,0]-1, conns[:,1]-1] = 1

Get corner values in Python numpy ndarray

I'm trying to access the corner values of a numpy ndarray. I'm absolutely stumped as for methodology. Any help would be greatly appreciated.
For example, from the below array I'd like a return value of array([1,0,0,5]) or array([[1,0],[0,5]]).
array([[ 1., 0., 0., 0.],
[ 0., 1., 0., 0.],
[ 0., 0., 1., 5.],
[ 0., 0., 5., 5.]])
To add variety to the answers, you can get a view (not a copy) of the corner items doing:
corners = a[::a.shape[0]-1, ::a.shape[1]-1]
Or, for a generic n-dimensional array:
corners = a[tuple(slice(None, None, j-1) for j in a.shape)]
Doing this, you can modify the original array by modifying the view:
>>> a = np.arange(9).reshape(3, 3)
>>> a
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> corners = a[tuple(slice(None, None, j-1) for j in a.shape)]
>>> corners
array([[0, 2],
[6, 8]])
>>> corners += 1
>>> a
array([[1, 1, 3],
[3, 4, 5],
[7, 7, 9]])
EDIT Ah, you want a flat list of corner values... That cannot in general be achieved with a view, so #IanH's answer is what you are looking for.
How about
A[[0,0,-1,-1],[0,-1,0,-1]]
where A is the array.
Use np.ix_ to construct the indices.
>>> a
array([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 5.],
[0., 0., 5., 5.]])
>>> corners = np.ix_((0,-1),(0,-1))
>>> a[corners]
array([[1., 0.],
[0., 5.]])
You can manually specify the corners (using negative indexes):
a = numpy.array([[ 1., 0., 0., 0.],
[ 0., 1., 0., 0.],
[ 0., 0., 1., 5.],
[ 0., 0., 5., 5.]])
result = numpy.array([a[0][0],a[0][-1],a[-1][0],a[-1][-1]])
# result will contain array([ 1., 0., 0., 5.])
result = numpy.array([a[0][0],a[0][-1],a[-1][0],a[-1][-1]])
# result will contain array([[ 1., 0.],
# [ 0., 5.]])

Categories

Resources