# Class #9 – More Lists and Numpy Arrays¶

## Higher Dimensions¶

Activity

Let’s say we have a list:

>>> a = ['a','b','c']

Questions:

What is the length of this list?

What is the type of the things in this list?

What do I type to get

`'a'`

printed out?

Answer these, and then test it in code.

Activity

OK cool, what if I do this:

```
>>> a = ['a','b','c']
>>> b = [a]
```

**Questions:**

What is the length of this list?

What is the type of the things in this list?

What do I type to get

`'a'`

printed out?

Answer these, and then test it in code.

Activity

What if I do this:

```
>>> a = ['a','b','c']
>>> b = [a, ['d', 'e', 'f']]
```

**Questions:**

What is the length of this list?

What is the type of the things in this list?

What do I type to get

`'a'`

printed out? Can you think of how you could do it two ways?

Answer these, and then test it in code.

Activity

Here’s a weird one:

```
>>> a = ['a','b','c']
>>> b = [a, a]
```

**Questions:**

What is the length of this list?

What is the type of the things in this list?

What do I type to get

`'a'`

printed out?What happens if I write this

`b[0][0] = 'Z'`

?

Answer these, and then test it in code.

Activity

Last one, I swear:

```
>>> a = ['a','b','c']
>>> b = [a, ['d', 'e', 'f']]
>>> c = [b, ['g', 'h', 'i']]
```

**Questions:**

What is the length of this list?

What is the type of the things in this list?

What do I type to get

`'a'`

printed out?

Answer these, and then test it in code.

## Numpy *Arrays*¶

Warning

Numpy *arrays* are a little different than classic arrays. Nothing too much to worry about, but just be aware.

The

*list*was our first data structure.Now we’re going to meet a similar, but slightly different, one: the numpy

*array*Let’s get started:

>>> import numpy >>> a = numpy.array([5,4,2]) >>> print(a) [5 4 2]

Looks a lot like a list, doesn’t it?

Can we manipulate it like a list?

>>> print(a[0]) 5

>>> print(a[1]) 4

We can definitely

*index*it, the same as a list.I wonder if arrays are

*mutable*?>>> a[1] = 7 >>> print(a) [5 7 2]

Yes, arrays are

*mutable*.With lists, I could mix types in a single list. Like this:

>>> l = [5,4,3] >>> l[2] = 'walrus' >>> print(l) [5, 4, 'walrus']

Can I do that with arrays?

>>> a = numpy.array([5,4,2]) >>> a[2] = 'walrus' ValueError: invalid literal for long() with base 10: 'walrus'

Ah ha! We found a way in which arrays are different.

Lists are just collections of stuff. Any old stuff. Each element can be of a different type.

In an array,

*every element must have the same type*!

Activity

Create two arrays of integers, each having the same number of elements.

What mathematical operations can you do on the arrays? (`+,-,*,/`

).

What happens if you try to perform the operations on arrays of different sizes?

How does `+`

work differently on arrays than lists?

## Numpy array object attributes and methods¶

Remember how I showed you how objects, like strings, had some

*methods*attached to them?Objects can also have

*attributes*We can ask numpy arrays what type the items in an array have like this:

>>> a.dtype dtype('int32')

- If you want to see all the attributes and methods your array has you can type
`a.`

(a dot) and then press the [Tab] key. Ones with parentheses are

*methods*Ones with no parentheses are

*attributes*

- If you want to see all the attributes and methods your array has you can type
That’s a lot of methods and attributes!

Some of those are things like

`dtype`

that store information about the state of the object (attributes).Some are special functions (methods) that can only be applied to that object

>>> a = numpy.array([5, 4, 2]) >>> print(a.sum()) 11

>>> print(a.max()) 5

>>> print(a.mean()) 3.6666666666666665

- When a function (method) appears after a
`.`

, that function is automatically applied to the object appearing before the`.`

These special functions built in to objects can also take parameters.

- When a function (method) appears after a
For example, we can change the types of the elements of our array:

>>> b = a.astype(float) >>> print(b) [ 5., 4., 2.]

## Making numpy arrays bigger¶

With lists, we could always append items to make them bigger

>>> a = [1, 2, 3] >>> a.append(5) >>> print(a) [1, 2, 3, 5]

Or even concatenate two lists together like this

>>> a = [1,2,3] + [5] >>> print(a) [1, 2, 3, 5]

Arrays are meant to have

*fixed*size.**Why do you think this is?**If you really, really, want to make an array bigger… you can’t.

You

*can*however, make a*new*array that is bigger using`numpy.append()`

:>>> a = numpy.array([1,2,3,4]) >>> print(a) [1, 2, 3, 4]

>>> b = numpy.append(a,5) >>> print(a) [1, 2, 3, 4]

>>> print(b) [1, 2, 3, 4, 5]

- Note that
`.append(...)`

here is a**FUNCTION**, not a method. What is the input parameters and types here?

What does this function return?

- Note that
**Note**carefully that`numpy.append()`

did*not*change*a*. It created a**new**array,*b*.This is also kinda’ like strings. Remember, we had to make copies of the string to make any changes?

Activity

Create an array of 4 integers.

Create a new, bigger, array by appending the integer `7`

on to your array.

Create another new array by appending the string `'walrus'`

.

Did that last one work? What happened?

## Flexibility vs Power¶

- Arrays are less flexible than lists:
We can’t change their size

They can only store data of a single type

But… it is this very lack of flexibility that lets us do all sorts of cool stuff (eg.

`.sum()`

)

Activity

How would you implement `.sum()`

for a list?

## Higher dimensions¶

Like lists, numpy arrays generalize to higher dimensions.

Let’s create a 2D array:

>>> a=numpy.array([[1,2,3],[4,5,6],[7,8,9]]) >>> print(a) [[1 2 3] [4 5 6] [7 8 9]]

Note the format in our call to

`numpy.array`

. A list of lists.Each row of the array gets its own list.

As long as two 2D arrays have the same

*shape*, you can do arithmetic on them, just like 1D arrays.- How do we check the
*shape*of an array? `.shape`

attribute

>>> print(a.shape) (3, 3)

- How do we check the

Activity

Create a 4x4 array. Verify that it has `shape`

`(4,4)`

.

You’ve changed your mind. The array should actually be 2x8. `reshape`

your 4x4 array in to a 2x8 array without recreating it from scratch.

Verify that the reshaped array is `(2,8)`

.

Finally `flatten`

your 2D array into a 1D array.

## Starting points¶

Sometimes you want an array of shape

`(n,m)`

that contains all zeros:>>> # The extra parentheses are important >>> a = numpy.zeros((n,m))

Guess what

`numpy.ones()`

does?How about

`numpy.eye()`

?

## Slicing¶

We’ve already seen that you can index arrays like lists (and strings)

Likewise, you can use Python’s powerful

*slicing*on arrays

Activity

- Create an array
`arr = numpy.array([0,1,2,3,4,5,6,7])`

. Using a single command Print the first 3 elements

Print the last 3 elements

Print the even elements of

`arr`

Slicing works for higher dimensional arrays, too. For example:

>>> a = numpy.arange(25).reshape(5,5) >>> print(a) [[ 0 1 2 3 4] [ 5 6 7 8 9] [10 11 12 13 14] [15 16 17 18 19] [20 21 22 23 24]]

>>> print(a[0:2,1:4]) [[1 2 3] [6 7 8]]

Note the use of

`numpy.arange`

which works like`range`

but returns an array.If you want a whole column/row/etc, you can use a plain

`:`

as the index. For example, if I wanted to pull out every row of the first two columns:>>> print a[:,0:2] [[ 0 1] [ 5 6] [10 11] [15 16] [20 21]]

Activity

Modify the previous command to print all of the columns of the first two *rows*.

## For loops¶

If

`for`

loops work for lists, do you think they’ll work for arrays?

Activity

Write a function `printeach(arr)`

that uses a `for`

loop to print each element of an array that is passed in as a parameter.

Test it on a 1D array.

Now try a 2D array.

If you’re feeling bold, how about a 3D array?