Numpy matrix minus a vector with repeated row/column indices - python

>>> a
array([[1, 2],
[3, 4],
[5, 6]])
>>>b
array([[1, 2],
[4, 3]])
What I want is doing
b[0,:]-=a[0,:], b[1,:]-=a[1,:], b[0,:]-=a[2,:]
But the following doesn't work:
>>> b[[0,1,0],:]-=a
>>> b
array([[-4, -4], # want [-5, -6]
[ 1, -1]])
How can this be achieved without using a for loop?

Use np.subtract.at -
np.subtract.at(b,[0,1,0],a)
Sample run -
In [15]: a
Out[15]:
array([[1, 2],
[3, 4],
[5, 6]])
In [16]: b
Out[16]:
array([[1, 2],
[4, 3]])
In [17]: np.subtract.at(b,[0,1,0],a)
In [18]: b
Out[18]:
array([[-5, -6],
[ 1, -1]])

Related

using numpy broadcast_to create a repeated view of every element in array

I want to repeat every element in an array n times without creating a new location on the memory to reproduce the same output as np.repeat shown below.
using np.broadcast_to i managed to only repeat the whole array n times not every element inside it.
arr = np.array([[1, 2], [3, 4]])
arr
array([[1, 2],
[3, 4]])
np.repeat(arr, 6, axis=0)
array([[1, 2],
[1, 2],
[1, 2],
[1, 2],
[1, 2],
[1, 2],
[3, 4],
[3, 4],
[3, 4],
[3, 4],
[3, 4],
[3, 4]])
In [57]: arr = np.array([[1,2],[3,4]])
In [58]: rarr = np.repeat(arr, 3, axis=0)
In [59]: rarr
Out[59]:
array([[1, 2],
[1, 2],
[1, 2],
[3, 4],
[3, 4],
[3, 4]])
You can't use broadcasting to duplicate this. The underlying raveled memory is different:
In [60]: arr.ravel()
Out[60]: array([1, 2, 3, 4])
In [61]: rarr.ravel()
Out[61]: array([1, 2, 1, 2, 1, 2, 3, 4, 3, 4, 3, 4])
With broadcast_to the regular broadcasting rules apply - new leading dimensions are automatic, and size 1 dimensions are scaled. Thus
In [64]: np.broadcast_to(arr, (3,2,2))
Out[64]:
array([[[1, 2],
[3, 4]],
[[1, 2],
[3, 4]],
[[1, 2],
[3, 4]]])
All values have been 'replicated', but the shape and order is different from your repeat. Any attempt to transpose and reshape elements will result in a copy (with no memory savings).
A different broadcasting produces a layout closer to the repeat:
In [70]: np.broadcast_to(arr[:,None,:], (2,3,2))
Out[70]:
array([[[1, 2],
[1, 2],
[1, 2]],
[[3, 4],
[3, 4],
[3, 4]]])
In [71]: np.broadcast_to(arr[:,None,:], (2,3,2)).reshape(6,2)
Out[71]:
array([[1, 2],
[1, 2],
[1, 2],
[3, 4],
[3, 4],
[3, 4]])
[70] is a view (readonly), but [71] is a copy, with the same memory footprint as rarr.

Concatenate indices of each Numpy Array in a Matrix

So I have a Numpy Array with a bunch of numpy arrays inside of them. I want to group them based on the position in their individual array.
For Example:
If Matrix is:
[[1, 2], [2, 3], [4, 5], [6, 7]]
Then the code should return:
[[1, 2, 4, 6], [2, 3, 5, 7]]
This is becuase 1, 2, 4, 6 are all the first elements in their individual arrays, and 2, 3, 5, 7 are the second elements in their individual arrays.
Anyone know some function that could do this. Thanks.
Answer in Python.
Using numpy transpose should do the trick:
a = np.array([[1, 2], [2, 3], [4, 5], [6, 7]])
a_t = a.T
print(a_t)
array([[1, 2, 4, 6],
[2, 3, 5, 7]])
Your data as a list:
In [101]: alist = [[1, 2], [2, 3], [4, 5], [6, 7]]
In [102]: alist
Out[102]: [[1, 2], [2, 3], [4, 5], [6, 7]]
and as a numpy array:
In [103]: arr = np.array(alist)
In [104]: arr
Out[104]:
array([[1, 2],
[2, 3],
[4, 5],
[6, 7]])
A standard idiom for 'transposing' lists is:
In [105]: list(zip(*alist))
Out[105]: [(1, 2, 4, 6), (2, 3, 5, 7)]
with arrays, there's a transpose method:
In [106]: arr.transpose()
Out[106]:
array([[1, 2, 4, 6],
[2, 3, 5, 7]])
The first array is (4,2) shape; its transpose is (2,4).

convert numpy open mesh to coordinates

I'd like to turn an open mesh returned by the numpy ix_ routine to a list of coordinates
eg, for:
In[1]: m = np.ix_([0, 2, 4], [1, 3])
In[2]: m
Out[2]:
(array([[0],
[2],
[4]]), array([[1, 3]]))
What I would like is:
([0, 1], [0, 3], [2, 1], [2, 3], [4, 1], [4, 3])
I'm pretty sure I could hack it together with some iterating, unpacking and zipping, but I'm sure there must be a smart numpy way of achieving this...
Approach #1 Use np.meshgrid and then stack -
r,c = np.meshgrid(*m)
out = np.column_stack((r.ravel('F'), c.ravel('F') ))
Approach #2 Alternatively, with np.array() and then transposing, reshaping -
np.array(np.meshgrid(*m)).T.reshape(-1,len(m))
For a generic case with for generic number of arrays used within np.ix_, here are the modifications needed -
p = np.r_[2:0:-1,3:len(m)+1,0]
out = np.array(np.meshgrid(*m)).transpose(p).reshape(-1,len(m))
Sample runs -
Two arrays case :
In [376]: m = np.ix_([0, 2, 4], [1, 3])
In [377]: p = np.r_[2:0:-1,3:len(m)+1,0]
In [378]: np.array(np.meshgrid(*m)).transpose(p).reshape(-1,len(m))
Out[378]:
array([[0, 1],
[0, 3],
[2, 1],
[2, 3],
[4, 1],
[4, 3]])
Three arrays case :
In [379]: m = np.ix_([0, 2, 4], [1, 3],[6,5,9])
In [380]: p = np.r_[2:0:-1,3:len(m)+1,0]
In [381]: np.array(np.meshgrid(*m)).transpose(p).reshape(-1,len(m))
Out[381]:
array([[0, 1, 6],
[0, 1, 5],
[0, 1, 9],
[0, 3, 6],
[0, 3, 5],
[0, 3, 9],
[2, 1, 6],
[2, 1, 5],
[2, 1, 9],
[2, 3, 6],
[2, 3, 5],
[2, 3, 9],
[4, 1, 6],
[4, 1, 5],
[4, 1, 9],
[4, 3, 6],
[4, 3, 5],
[4, 3, 9]])

Numpy switch numbering from columns to rows

I need to change the numbering scheme of a matrix. Say,
import numpy as np
a = np.arange(6).reshape(3,2)
array([[0, 1],
[2, 3],
[4, 5]])
And I want to switch it to
b = np.array([[0,3],[1,4],[2,5]])
array([[0, 3],
[1, 4],
[2, 5]])
So that basically I number the matrix through the rows first. I am sure there is a nice way to do this in numpy
>>> import numpy as np
>>> np.arange(6).reshape(3,2, order = 'F')
>>> array([[0, 3],
[1, 4],
[2, 5]])
From the doc:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html
Use order='F' to specify the Fortran traditional representation and order='C' (the default) to use the traditional C representation.
To create a view of the same data with the new shape, you can use a.T.reshape(3, 2, order='F'):
In [35]: a = np.arange(6).reshape(3,2)
In [36]: a
Out[36]:
array([[0, 1],
[2, 3],
[4, 5]])
In [37]: b = a.T.reshape(3, 2, order='F')
In [38]: b
Out[38]:
array([[0, 3],
[1, 4],
[2, 5]])
Verify a and b are views of the same data, by changing a and checking b:
In [39]: a[1, 0] = 99
In [40]: a
Out[40]:
array([[ 0, 1],
[99, 3],
[ 4, 5]])
In [41]: b
Out[41]:
array([[ 0, 3],
[ 1, 4],
[99, 5]])

Python - Matrix outer product

Given two matrices
A: m * r
B: n * r
I want to generate another matrix C: m * n, with each entry C_ij being a matrix calculated by the outer product of A_i and B_j.
For example,
A: [[1, 2],
[3, 4]]
B: [[3, 1],
[1, 2]]
gives
C: [[[3, 1], [[1 ,2],
[6, 2]], [2 ,4]],
[9, 3], [[3, 6],
[12,4]], [4, 8]]]
I can do it using for loops, like
for i in range (A.shape(0)):
for j in range (B.shape(0)):
C_ij = np.outer(A_i, B_j)
I wonder If there is a vectorised way of doing this calculation to speed it up?
The Einstein notation expresses this problem nicely
In [85]: np.einsum('ac,bd->abcd',A,B)
Out[85]:
array([[[[ 3, 1],
[ 6, 2]],
[[ 1, 2],
[ 2, 4]]],
[[[ 9, 3],
[12, 4]],
[[ 3, 6],
[ 4, 8]]]])
temp = numpy.multiply.outer(A, B)
C = numpy.swapaxes(temp, 1, 2)
NumPy ufuncs, such as multiply, have an outer method that almost does what you want. The following:
temp = numpy.multiply.outer(A, B)
produces a result such that temp[a, b, c, d] == A[a, b] * B[c, d]. You want C[a, b, c, d] == A[a, c] * B[b, d]. The swapaxes call rearranges temp to put it in the order you want.
Simple Solution with Numpy Array Broadcasting
Since, you want C_ij = A_i * B_j, this can be achieved simply by numpy broadcasting on element-wise-product of column-vector-A and row-vector-B, as shown below:
# import numpy as np
# A = [[1, 2], [3, 4]]
# B = [[3, 1], [1, 2]]
A, B = np.array(A), np.array(B)
C = A.reshape(-1,1) * B.reshape(1,-1)
# same as:
# C = np.einsum('i,j->ij', A.flatten(), B.flatten())
print(C)
Output:
array([[ 3, 1, 1, 2],
[ 6, 2, 2, 4],
[ 9, 3, 3, 6],
[12, 4, 4, 8]])
You could then get your desired four sub-matrices by using numpy.dsplit() or numpy.array_split() as follows:
np.dsplit(C.reshape(2, 2, 4), 2)
# same as:
# np.array_split(C.reshape(2,2,4), 2, axis=2)
Output:
[array([[[ 3, 1],
[ 6, 2]],
[[ 9, 3],
[12, 4]]]),
array([[[1, 2],
[2, 4]],
[[3, 6],
[4, 8]]])]
Use numpy;
In [1]: import numpy as np
In [2]: A = np.array([[1, 2], [3, 4]])
In [3]: B = np.array([[3, 1], [1, 2]])
In [4]: C = np.outer(A, B)
In [5]: C
Out[5]:
array([[ 3, 1, 1, 2],
[ 6, 2, 2, 4],
[ 9, 3, 3, 6],
[12, 4, 4, 8]])
Once you have the desired result, you can use numpy.reshape() to mold it in almost any shape you want;
In [6]: C.reshape([4,2,2])
Out[6]:
array([[[ 3, 1],
[ 1, 2]],
[[ 6, 2],
[ 2, 4]],
[[ 9, 3],
[ 3, 6]],
[[12, 4],
[ 4, 8]]])

Categories

Resources