Matrix multiplying arrays with Numpy - python

I have a 5x5 array of arrays and I'm trying to matrix multiply the transpose of one row with another row.
import numpy as np
a = np.array([1, 4, 6, 4, 1])
b = np.array([-1, -2, 0, 2, 1])
c = np.array([-1, 2, 0, -2, 1])
d = np.array([-1, 0, 2, 0, -1])
e = np.array([1, -4, 6, -4, 1])
f = np.vstack([a, b, c, d, e])
result = np.dot(f[1, :].T, f[1, :])
I assumed this would work but apparently
f[1, :].T
ends up becoming
[-1, -2, 0, 2, 1]
rather than
[[-1]
[-2]
[ 0]
[ 2]
[ 1]]
and so np.dot treats it like a real dot product rather than doing matrix multiplication.
I found out that list slicing where one index is an integer and all others are :s reduces the dimension by one so so the shape of f[1, :] is not (1, 5) but (5,) and so transposing it does nothing.
I've been able to get it to working using f[1, :].reshape((1, 5)) but is there a better way of doing this? Am I missing a simple way of getting the transpose without having to reshape it?

You can use np.newaxis to add a dimension when slicing, to compensate for the dimension that is otherwise lost.
f[1, :, np.newaxis]
produces the single-column 2D array you want. Putting np.newaxis before the colon would give a single-row 2D array.

For numpy arrays it is often favorable to have this behavior, to circumvent this you can always use the numpy matrix class.
>>> f = np.matrix(f)
>>> f
matrix([[ 1, 4, 6, 4, 1],
[-1, -2, 0, 2, 1],
[-1, 2, 0, -2, 1],
[-1, 0, 2, 0, -1],
[ 1, -4, 6, -4, 1]])
>>> f[1,:].T
matrix([[-1],
[-2],
[ 0],
[ 2],
[ 1]])
>>> np.dot(f[1, :].T, f[1, :])
matrix([[ 1, 2, 0, -2, -1],
[ 2, 4, 0, -4, -2],
[ 0, 0, 0, 0, 0],
[-2, -4, 0, 4, 2],
[-1, -2, 0, 2, 1]])
As this is the matrix class * will denote matrix multiplication, therefore you can simply use:
f[1,:].T * f[1,:]
Also you may want to consider np.outer for this kind of operation:
>>> np.outer(f[1,:],f[1,:])
array([[ 1, 2, 0, -2, -1],
[ 2, 4, 0, -4, -2],
[ 0, 0, 0, 0, 0],
[-2, -4, 0, 4, 2],
[-1, -2, 0, 2, 1]])

If you want the individual slices to retain their "matrixness" then you should cast f to a numpy.matrix, which preserves the matrixness.
fm = numpy.matrix(f)
then
numpy.dot(fm[1,:].T,fm[1,:])
will return an nxn matrix

Following the accepted answer, I prefer to use None instead of np.newaxis, which is a little verbose for my tastes. For example,
f[:,None]
does the same thing as f[:,np.newaxis].

I am late to the party here, it is worth noting that the NumPy webpage I accessed today warns that
class numpy.matrix(data, dtype=None, copy=True)
might be removed.

Related

Pairwise difference of vectors

Say i have a matrix that is composed of N vectors as columns: matrix=[v_1, v_2, .. v_N] where v is from R^N. I want a new matrix that gives: for all (r in N, s in N) v(r)-v(s). For example if N=3, then i want a 3x3x3 and for a particular index i,j,k, it Represents the kth index of v(i)-v(j).
You can use broadcasting on a new dimension:
out = matrix[:,None]-matrix
Example:
matrix = np.arange(9).reshape(3,3)
out = matrix[:,None]-matrix
Output:
array([[[ 0, 0, 0],
[-3, -3, -3],
[-6, -6, -6]],
[[ 3, 3, 3],
[ 0, 0, 0],
[-3, -3, -3]],
[[ 6, 6, 6],
[ 3, 3, 3],
[ 0, 0, 0]]])

Numpy efficient indexing with varied size arrays

Take a look at this piece of code:
import numpy as np
a = np.random.random(10)
indicies = [
np.array([1, 4, 3]),
np.array([2, 5, 8, 7, 3]),
np.array([1, 2]),
np.array([3, 2, 1])
]
result = np.zeros(2)
result[0] = a[indicies[0]].sum()
result[1] = a[indicies[2]].sum()
Is there any way to get result more efficiently? In my case a is a very large array.
In other words I want to select elements from a with several varying size index arrays and then sum over them in one operation, resulting in a single array.
With your a and indicies list:
In [280]: [a[i].sum() for i in indicies]
Out[280]:
[1.3986792680307709,
2.6354365193743732,
0.83324677494990895,
1.8195179021311731]
Which of course could wrapped in np.array().
For a subset of the indicies items use:
In [281]: [a[indicies[i]].sum() for i in [0,2]]
Out[281]: [1.3986792680307709, 0.83324677494990895]
A comment suggests indicies comes from an Adjacency matrix, possibly sparse.
I could recreate such an array with:
In [289]: A=np.zeros((4,10),int)
In [290]: for i in range(4): A[i,indicies[i]]=1
In [291]: A
Out[291]:
array([[0, 1, 0, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 1, 0, 1, 1, 0],
[0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 1, 1, 0, 0, 0, 0, 0, 0]])
and use a matrix product (np.dot) to do the selection and sum:
In [292]: A.dot(a)
Out[292]: array([ 1.39867927, 2.63543652, 0.83324677, 1.8195179 ])
A[[0,2],:].dot(a) would use a subset of rows.
A sparse matrix version has that list of row indices:
In [294]: Al=sparse.lil_matrix(A)
In [295]: Al.rows
Out[295]: array([[1, 3, 4], [2, 3, 5, 7, 8], [1, 2], [1, 2, 3]], dtype=object)
And a matrix product with that gives the same numbers:
In [296]: Al*a
Out[296]: array([ 1.39867927, 2.63543652, 0.83324677, 1.8195179 ])
If your array a is very large you might have memory issues if your array of indices contains many arrays of many indices when looping through it.
To avoid this issue use an iterator instead of a list :
indices = iter(indices)
and then loop through your iterator.

Numpy Matrix Difference row by row into 3D tensor [duplicate]

I know I can do np.subtract.outer(x, x). If x has shape (n,), then I end up with an array with shape (n, n). However, I have an x with shape (n, 3). I want to output something with shape (n, n, 3). How do I do this? Maybe np.einsum?
You can use broadcasting after extending the dimensions with None/np.newaxis to form a 3D array version of x and subtracting the original 2D array version from it, like so -
x[:, np.newaxis, :] - x
Sample run -
In [6]: x
Out[6]:
array([[6, 5, 3],
[4, 3, 5],
[0, 6, 7],
[8, 4, 1]])
In [7]: x[:,None,:] - x
Out[7]:
array([[[ 0, 0, 0],
[ 2, 2, -2],
[ 6, -1, -4],
[-2, 1, 2]],
[[-2, -2, 2],
[ 0, 0, 0],
[ 4, -3, -2],
[-4, -1, 4]],
[[-6, 1, 4],
[-4, 3, 2],
[ 0, 0, 0],
[-8, 2, 6]],
[[ 2, -1, -2],
[ 4, 1, -4],
[ 8, -2, -6],
[ 0, 0, 0]]])

Logical indexing in python for nd arrays

I am trying to extract all the indexes from an (N x N x N) numpy array, where values in both A and B arrays are equal to some value x - find the common overlap.
I am trying:
A[A==1 and B==1]
but get an error:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
How do I get around this?
Numpy cannot overload the "and" keyword. However it overloads the binary AND operator & for this. Try:
A[(A==1) & (B==1)]
The parantheses are important. I find it often (not always)better readable then logical_and
A == 1 and B == 1 are boolean arrays, while (A==1)*(B==1) is an array of integers. You can find the nonzero entries of this array through NumPy's where:
np.where((A==1)*(B==1))
Demo
Consider the following 3-dimensional arrays, which are randomly populated with values -1, 0 and 1:
In [1066]: import numpy as np
In [1067]: np.random.seed(2016) # this is to get the same results on multiple runs
In [1068]: N = 3
...: A = np.random.randint(low=-1, high=2, size=(N, N, N))
...: B = np.random.randint(low=-1, high=2, size=(N, N, N))
In [1069]: A
Out[1069]:
array([[[ 1, 1, 0],
[-1, 1, -1],
[-1, -1, -1]],
[[ 0, 1, 1],
[-1, 1, 1],
[ 0, 1, 0]],
[[ 0, 1, 0],
[-1, 1, 1],
[-1, 1, 0]]])
In [1070]: B
Out[1070]:
array([[[-1, 0, 0],
[-1, -1, 1],
[ 0, -1, -1]],
[[-1, -1, -1],
[-1, 1, 1],
[-1, 1, 1]],
[[ 1, 1, -1],
[-1, 0, 1],
[-1, 1, -1]]])
The function where returns a tuple of integer arrays which triggers advanced indexing:
In [1071]: idx = np.where((A==1)*(B==1))
In [1072]: idx
Out[1072]:
(array([1, 1, 1, 2, 2, 2], dtype=int64),
array([1, 1, 2, 0, 1, 2], dtype=int64),
array([1, 2, 1, 1, 2, 1], dtype=int64))
In [1073]: A[idx]
Out[1073]: array([1, 1, 1, 1, 1, 1])
In [1074]: B[idx]
Out[1074]: array([1, 1, 1, 1, 1, 1])
perhaps slightly hasty posting this question. Used numpy's
logical_and(x1, x2[, out])
in the end which did the job perfectly!

Compute Jordan normal form of matrix in Python / NumPy

In MATLAB you can compute the Jordan normal form of a matrix by using the the function jordan.
It there an equivalent function available in NumPy and SciPy?
The MATLAB jordan function is from the Symbolic Math Toolbox, so it does not seem unreasonable to get its Python replacement from the SymPy library. Specifically, the Matrix class has the method jordan_form. You can pass a numpy array as an argument when you create a sympy Matrix. For example, the following is from the wikipedia article on the Jordan normal form:
In [1]: import numpy as np
In [2]: from sympy import Matrix
In [3]: a = np.array([[5, 4, 2, 1], [0, 1, -1, -1], [-1, -1, 3, 0], [1, 1, -1, 2]])
In [4]: m = Matrix(a)
In [5]: m
Out[5]:
Matrix([
[ 5, 4, 2, 1],
[ 0, 1, -1, -1],
[-1, -1, 3, 0],
[ 1, 1, -1, 2]])
In [6]: P, J = m.jordan_form()
In [7]: J
Out[7]:
Matrix([
[1, 0, 0, 0],
[0, 2, 0, 0],
[0, 0, 4, 1],
[0, 0, 0, 4]])
There's this implementation.
It will definitely not be as fast as MATLAB, though.

Categories

Resources