Algorithms For Dummies. John Paul Mueller
vectors as a whole, which makes
numpy
incredibly useful and less prone to errors that can occur when using programming constructs such as loops to perform the same task. For example, when starting with myVect = np.array([1, 2, 3, 4])
, myVect + 1
produces an output of array([2, 3, 4, 5], dtype=int16)
. Note that the output tells you specifically which data type is in use. As you might expect, myVect - 1
produces an output of array([0, 1, 2, 3], dtype=int16)
.
As a final thought on scalar and vector operations, you can also perform both logical and comparison tasks. For example, the following code performs comparison operations on two arrays:
a = np.array([1, 2, 3, 4])b = np.array([2, 2, 4, 4]) print(a == b)print(a < b)
The output in this case is:
[False True False True][ True False True False]
Starting with two vectors, a
and b
, the code checks whether the individual elements in a
equal those in b
. In this case, a[0]
doesn't equal b[0]
. However, a[1]
does equal b[1]
. The output is a vector of type bool
that contains True
or False
values based on the individual comparisons.
Logical operations rely on special functions. You check the logical output of the Boolean operators AND, OR, XOR, and NOT. Here is an example of the logical functions:
a = np.array([True, False, True, False])b = np.array([True, True, False, False]) print(np.logical_or(a, b))print(np.logical_and(a, b))print(np.logical_not(a))print(np.logical_xor(a, b))
When you run this code, you see these outputs:
[ True True True False][ True False False False][False True False True][False True True False]
You can read more about the logic functions at https://numpy.org/doc/stable/reference/routines.logic.html
.
Performing vector multiplication
Adding, subtracting, or dividing vectors occurs on an element-by-element basis, as described in the previous section. However, when it comes to multiplication, things get a little odd. In fact, depending on what you really want to do, things can become quite odd indeed. Consider the sort of multiplication discussed in the previous section. Both myVect * myVect
and np.multiply(myVect, myVect)
produce an element-by-element output of [ 1, 4, 9, 16] when starting with an array of [1, 2, 3, 4].
Unfortunately, an element-by-element multiplication can produce incorrect results when working with algorithms. In many cases, what you really need is a dot product, which is the sum of the products of two number sequences. When working with vectors, the dot product is always the sum of the individual element-by-element multiplications and results in a single number. For example,
myVect.dot(myVect)
results in an output of 30
. If you sum the values from the element-by-element multiplication, you find that they do indeed add up to 30. The discussion at https://www.mathsisfun.com/algebra/vectors-dot-product.html
tells you about dot products and helps you understand where they might fit in with algorithms. You can learn more about the linear algebra manipulation functions for numpy
at https://numpy.org/doc/stable/reference/routines.linalg.html
.
Creating a matrix is the right way to start
Many of the same techniques you use with vectors also work with matrixes. To create a basic matrix, you simply use the array()
function as you would with a vector, but you define additional dimensions. A dimension is a direction in the matrix. For example, a two-dimensional matrix contains rows (one direction) and columns (a second direction). The array call myMatrix = np.array([[1,2,3], [4,5,6], [7,8,9]])
produces a matrix containing three rows and three columns, like this:
[[1 2 3] [4 5 6] [7 8 9]]
Note how you embed three lists within a container list to create the two dimensions. To access a particular array element, you provide a row and column index value, such as myMatrix[0, 0]
to access the first value of 1
. You can find a full listing of vector and matrix array-creation functions at https://numpy.org/doc/stable/reference/routines.array-creation.html
.
matrix
class. The matrix
class supports special features that make it easier to perform matrix-specific tasks. You discover these features later in the chapter. For now, all you really need to know is how to create a matrix of the matrix
data type. The easiest method is to make a call similar to the one you use for the array
function, but using the mat
function instead, such as myMatrix = np.mat([[1,2,3], [4,5,6], [7,8,9]])
, which produces the following matrix:
[[1 2 3] [4 5 6] [7 8 9]]
To determine that this actually is a matrix, try print(type(myMatrix))
, which outputs <class 'numpy.matrix'>
. You can also convert an existing array to a matrix using the asmatrix()
function. Use the asarray()
function to convert a matrix
object back to an array
form.
The only problem with the
matrix
class is that it works on only two-dimensional matrixes. If you attempt to convert a three-dimensional matrix to the matrix
class, you see an error message telling you that the shape is too large to be a matrix.
Multiplying matrixes
Multiplying two matrixes involves the same concerns as multiplying two vectors (as discussed in the “Performing vector multiplication” section, earlier in this chapter). The following code produces an element-by-element multiplication of two matrixes:
a = np.array([[1,2,3],[4,5,6]])b = np.array([[1,2,3],[4,5,6]]) print(a*b)
The output looks like this:
[[ 1 4 9] [16 25 36]]
Note that
a
and b
are the same shape: two rows and three columns. To perform an element-by-element multiplication, the two matrixes must be the same shape. Otherwise, you see an error message telling you that the shapes are wrong. As with vectors, the multiply()
function also produces an element-by-element result.
Dot products work completely differently with matrixes. In this case, the number of columns in matrix a
must match the number of rows in matrix b
. However, the number of rows in matrix a
can be any number, and the number of columns in matrix b
can be any number as long as you multiply a
by b
. For example, the following code produces a correct dot product:
a = np.array([[1,2,3],[4,5,6]])b = np.array([[1,2,3],[3,4,5],[5,6,7]]) print(a.dot(b))
with an output of:
[[22 28 34] [49 64 79]]