```
In [ ]:
```%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import random

Create an 8x10 array of zeros called `my_array`

. Note that you can do this with any numpy array method (`ones`

, `zeros_like`

, `ones_like`

, etc.). See this page for a full list of routines for array creation.

```
In [ ]:
```a = np.zeros([8,10])
print(a)

`np.array`

a list. You can make a multi-dimensional numpy array by giving `np.array`

a set of nested lists (i.e., a list of lists). The following will create a 3x3 array with predetermined values:

```
In [ ]:
```b = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(b)

`.shape`

property tells you how large the array is in each dimension, `.ndim`

tells you the number of dimensions, and `.size`

tells you the total number of elements in the array. You can access each of the dimensions `dim`

by `.shape[dim]`

.

```
In [ ]:
```print("the shape of this array is:", a.shape)
print("there are:", a.ndim, "dimensions")
print("there are", a.size, "total elements")
for i in range(a.ndim):
print("the size of dimension", i, "is", a.shape[i])

You can manipulate individual cells of an array by:

`a[index_1,index_2]`

Note that when you print it, the first index corresponds to rows (counting down from the top) and the second index corresponds to columns (counting from the left). Indices in both directions count by zeros.

```
In [ ]:
```a[2,6]=11
#print entire array
print(a)
#print a single element of the array
print(a[2,6])

You can also use the same type of slicing that you use with lists - in other words, python allows you to select some subset of the elements in a list or an array to manipulate or copy. With slicing, there are three values that can be used along each dimension: `start`

,`end`

, and `step`

, separated by colons. Here are some examples in 1D:

```
myarray[start,end] # items start through end-1
myarray[start:] # items start through the end of the array
myarray[:end] # items from the beginning of the array through end-1
myarray[:] # a copy of the whole array
myarray[start,end,step] # every "step" item from start to end-1
myarray[::step] # every "step" item over the whole array, starting with the first element.
```

Note that negative indices count from the end of the array, so `myarray[-1]`

is the last element in the array, `myarray[-2]`

is the second-to-last element, etc. You can also reverse the order of the array by starting at the end and counting to the beginning by negative numbers -- in other words, `myarray[-1::-1]`

starts at the end of the array and goes to the first element by counting down by one each time.

```
In [ ]:
```# create a 1D array with values 0...10
c = np.arange(0,10)
# note: the '\n' at the beginning of many of the print statements
# adds a carriage return (blank line)
print("some elements from the middle of the array:",c[3:7] )
print("\nthe second element through the second-to-last element:", c[2:-1])
print("\nthe first half of the array:", c[:5])
print("\nthe second half of the array:", c[5:])
print("\nevery other element from 2-8 (inclusive):",c[2:9:2])
print("\nevery third element in the array:",c[::3])
print("\nreverse the array:",c[-1::-1])

The same sort of technique can be used with a multi-dimensional array, with `start`

, `stop`

, and (optionally) `step`

specified along each dimension, with the dimensions separated by a comma. The syntax would be:

`my2Darray[start1:stop1:step1, start2:stop2:step2]`

With the same rules as above. You can also combine slicing with fixed indices to get some or all elements from a single row or column of your array.

For example, array `b`

created above is a 3x3 array with the values 1-9 stored in it. We can do several different things:

```
b[0,:] # get the first row
b[:,2] # get the third column
b[1,::2] # get every other element of the first row, starting at element 0
b[:2,:2] # get a square array containing the first two elements along each dimension
b[-2:,-2:] # get a square array containing the last two elements along each dimension
b[::2,::2] # get a square array of every other element along each dimension
b[-1::-1,-1::-1] # original sized array, but reversed along both dimensions
```

```
In [ ]:
```print("the array b:\n",b,"\n")
# To get a square array containing the first two elements along each dimension:
print("the first row:", b[0,:])
print("\nthe third column:",b[:,2])
print("\nevery other element of the second row, starting with element 0:",b[1,::2])
print("\nsquare array of first two elements along each dimension:\n",b[:2,:2])
print("\nsquare array of last two elements along each dimension:\n",b[-2:,-2:])
print("\nsquare array of every other element along each dimension:\n",b[::2,::2])
print("\nreversed array:\n",b[-1::-1,-1::-1])

```
In [ ]:
```c = np.full((4,4),10.0) # makes an array of shape (4,4) where all elements are value 10.0
d = c
print("c:\n",c, "\nd:\n", d)

```
In [ ]:
```d[:,0] = -1.0 # make column 0 equal to -1
d[:,2] = -6.0 # make column 2 equal to -6
print("c:\n",c, "\nd:\n", d)

Arrays `c`

and `d`

are identical, even though you only changed `d`

!

So what's going on here? When you equate arrays in Numpy (i.e., `d = c`

), you create a **reference**, rather than copying the array -- in other words, the array `d`

is not a distinct array, but rather *points to* the array `c`

in memory. Any modification to either `c`

or `d`

will be seen by both. To actually make a copy, you have to use the `np.copy()`

method:

```
In [ ]:
```e = np.full((4,4),10.0) # makes an array of shape (4,4) where all elements are value 10.0
f = np.copy(e)
f[:,0] = -1.0 # make column 0 equal to -1
f[:,2] = -6.0 # make column 2 equal to -6
print("e:\n",e, "\nf:\n", f)

You can also make a copy of a subset of an arrays:

```
In [ ]:
```g = np.full((4,4),10.0) # makes an array of shape (4,4) where all elements are value 10.0
h = np.copy(g[0:2,0:2])
print("g:\n",g, "\nh:\n", h)

```
In [ ]:
```i = np.full((4,4),10.0) # makes an array of shape (4,4) where all elements are value 10.0
j = i[0:2,0:2]
print("\nunmodified arrays:\n")
print("i:\n",i, "\nj:\n", j)
print("\narrays after modification:\n")
j[1,1]=-999.0
print("i:\n",i, "\nj:\n", j)

Numpy has a `random`

module that can be used to generate random numbers in a similar way to the standard Python `random`

module, but with the added advantage that it can do so for arrays of values. Two commonly-used methods are:

```
In [ ]:
```random_float_array = np.random.random((5,5))
print(random_float_array)
random_int_array = np.random.randint(0,10,(5,5))
print("\n",random_int_array)

It's easy to plot 2D Numpy arrays in matplotlib using the pyplot `matshow`

method:

```
In [ ]:
```new_rand_array = np.random.random((100,100))
plt.matshow(new_rand_array)
# uncomment the following line to save the figure to your hard drive!
#plt.savefig("myimage.png")

And you can turn off the array axes with the following incantation:

```
In [ ]:
```myplot = plt.matshow(new_rand_array)
myplot.axes.get_xaxis().set_visible(False)
myplot.axes.get_yaxis().set_visible(False)

```
In [ ]:
```# interpolation='none' keeps imshow() from trying to interpolate between values and
# making it look fuzzy.
# cmap='mapname' changes the color map.
# vmin, vmax sets the range of the color bar (from 0.0 - 0.5 in this example)
myplot = plt.imshow(new_rand_array, interpolation='none',cmap='hot',vmin=0.0,vmax=0.5)
# uncomment the following lines to remove the axis labels
#myplot.axes.get_xaxis().set_visible(False)
#myplot.axes.get_yaxis().set_visible(False)
# uncomment the following line to save the figure to your hard drive!
#plt.savefig("myimage.png")