Time for action – creating a multidimensional array

Now that we know how to create a vector, we are ready to create a multidimensional NumPy array. After we create the array, we will again want to display its shape:

  1. Create a two-by-two array:
    In: m = array([arange(2), arange(2)])
    In: m
    Out:
    array([[0, 1],
          [0, 1]])
    
  2. Show the array shape:
    In: m.shape
    Out: (2, 2)
    

What just happened?

We created a two-by-two array with the arange() and array() functions we have come to trust and love. Without any warning, the array() function appeared on the stage.

The array() function creates an array from an object that you give to it. The object needs to be array-like, for instance, a Python list. In the preceding example, we passed in a list of arrays. The object is the only required argument of the array() function. NumPy functions tend to have a lot of optional arguments with predefined defaults. View the documentation for this function from the IPython shell with the help() function given here:

In [1]: help(array)

Or use the following shorthand:

In [2]: array?

Of course, you can substitute array in this example with another NumPy function you are interested in.

Pop quiz – the shape of ndarray

Q1. How is the shape of an ndarray stored?

  1. It is stored in a comma-separated string.
  2. It is stored in a list.
  3. It is stored in a tuple.

Have a go hero – create a three-by-three array

It shouldn't be too hard now to create a three-by-three array. Give it a go and check whether the array shape is as expected.

Selecting elements

From time to time, we will want to select a particular element of an array. We will take a look at how to do this, but, first, create a two-by-two array again:

In: a = array([[1,2],[3,4]])
In: a
Out:
array([[1, 2],
       [3, 4]])

The array was created this time by passing a list of lists to the array() function. We will now select one by one each item of the matrix. Remember, the indices are numbered starting from 0:

In: a[0,0]
Out: 1
In: a[0,1]
Out: 2
In: a[1,0]
Out: 3
In: a[1,1]
Out: 4

As you can see, selecting elements of the array is pretty simple. For the array a, we just use the notation a[m,n], where m and n are the indices of the item in the array (the array can have even more dimensions than in this example). This screenshot shows a simple example of an array:

Selecting elements

NumPy numerical types

Python has an integer type, a float type, and a complex type; however, this is not enough for scientific computing and, for this reason, NumPy has a lot more data types with varying precision, dependent on memory requirements.

Note

Integers represent whole numbers, such as -1, 0, and 1. Floating-point numbers correspond to real numbers as used in mathematics, for example, fractions or irrational numbers such as pi. Because of the way computers work, we are able to represent integers exactly, but floating-point numbers are approximated. Complex numbers can have an imaginary component usually denoted with i or j. By definition, i is the square root of -1. For instance, 2.5 + 3.7i is a complex number (for more information, refer to https://www.khanacademy.org/math/precalculus/imaginary_complex_precalc).

In practice, we need even more types with varying precision and, therefore, different memory size of the type. The majority of the NumPy numerical types end with a number. This number indicates the number of bits associated with the type. The following table (adapted from the NumPy user guide) gives an overview of NumPy numerical types:

Type

Description

bool

Boolean (True or False) stored as a bit

inti

Platform integer (normally either int32 or int64)

int8

Byte (-128 to 127)

int16

Integer (-32768 to 32767)

int32

Integer (-2 ** 31 to 2 ** 31 -1)

int64

Integer (-2 ** 63 to 2 ** 63 -1)

uint8

Unsigned integer (0 to 255)

uint16

Unsigned integer (0 to 65535)

uint32

Unsigned integer (0 to 2 ** 32 - 1)

uint64

Unsigned integer (0 to 2 ** 64 - 1)

float16

Half precision float: sign bit, 5 bits exponent, 10 bits mantissa

float32

Single precision float: sign bit, 8 bits exponent, 23 bits mantissa

float64 or float

Double precision float: sign bit, 11 bits exponent, 52 bits mantissa

complex64

Complex number, represented by two 32-bit floats (real and imaginary components)

complex128 or complex

Complex number, represented by two 64-bit floats (real and imaginary components)

For floating-point types, we can request information with the finfo() function given here:

In: finfo(float16)
Out: finfo(resolution=0.0010004, min=-6.55040e+04, max=6.55040e+04, dtype=float16)

For each data type, there exists a corresponding conversion function:

In: float64(42)
Out: 42.0
In: int8(42.0)
Out: 42
In: bool(42)
Out: True
In: bool(0)
Out: False
In: bool(42.0)
Out: True
In: float(True)
Out: 1.0
In: float(False)
Out: 0.0

Many functions have a data type argument, which is often optional:

In: arange(7, dtype=uint16)
Out: array([0, 1, 2, 3, 4, 5, 6], dtype=uint16)

It is important to know that you are not allowed to convert a complex number into an integer or float. Trying to do that triggers a TypeError, as shown in the following screenshot:

NumPy numerical types

The same goes for conversion of a complex number into a float.

Note

An exception in Python is an abnormal condition, which we usually try to avoid. A TypeError is a Python built-in exception, occurring when we specify the wrong type for an argument.

The j part is the imaginary coefficient of the complex number. However, you can convert a float in to a complex number, for instance, complex(1.0).

Data type objects

Data type objects are instances of the numpy.dtype class. Once again, arrays have a data type. To be precise, every element in a NumPy array has the same data type. The data type object can tell you the size of the data in bytes. The size in bytes is given by the itemsize attribute of the dtype class:

In: a.dtype.itemsize
Out: 8

Character codes

Character codes are included for backward compatibility with Numeric. Numeric is the predecessor of NumPy. Their use is not recommended, but the codes are provided here because they pop up in several places. We should instead use the dtype objects. The table shows the character codes:

Type

Character code

Integer

i

Unsigned integer

u

Single precision float

f

Double precision float

d

Boolean

b

Complex

D

String

S

Unicode

U

Void

V

Look at the following code to create an array of single precision floats:

In: arange(7, dtype='f')
Out: array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.], dtype=float32)

Likewise this creates an array of complex numbers.

In: arange(7, dtype='D')
Out: array([ 0.+0.j,  1.+0.j,  2.+0.j,  3.+0.j,  4.+0.j,  5.+0.j,  6.+0.j])

The dtype constructors

Python classes have functions, which are called methods, if they belong to a class. Some of these methods are special and used to create new objects. These specialized methods are called constructors.

Note

You can read more about Python classes at https://docs.python.org/2/tutorial/classes.html.

We have a variety of ways to create data types. Take the case of floating point data:

  • Use the general Python float:
    In: dtype(float)
    Out: dtype('float64')
    
  • Specify a single precision float with a character code:
    In: dtype('f')
    Out: dtype('float32')
    
  • Use a double precision float character code:
    In: dtype('d')
    Out: dtype('float64')
    
  • We can give the data type constructor a two-character code. The first character signifies the type and the second character is a number specifying the number of bytes in the type (the numbers 2, 4, and 8 correspond to 16, 32, and 64-bit floats):
    In: dtype('f8')
    Out: dtype('float64')
    

A listing of all full data type names can be found with the sctypeDict.keys() function:

In: sctypeDict.keys()
Out: [0, …
 'i2',
 'int0']

The dtype attributes

The dtype class has a number of useful attributes. For example, get information about the character code of a data type through the attributes of dtype:

In: t = dtype('Float64')
In: t.char
Out: 'd'

The type attribute corresponds to the type of object of the array elements:

In: t.type
Out: <type 'numpy.float64'>

The str attribute of the dtype class gives a string representation of the data type. It starts with a character representing endianness, if appropriate, then a character code, followed by a number corresponding to the number of bytes that each array item requires. Endianness, here, refers to the way bytes are ordered within a 32- or 64-bit word. In big-endian order, the most significant byte is stored first, indicated by >. In little-endian order, the least significant byte is stored first, indicated by <:

In: t.str
Out: '<f8'
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset