You are currently looking at version 1.1 of this notebook. To download notebooks and datafiles, as well as get help on Jupyter notebooks in the Coursera platform, visit the Jupyter Notebook FAQ course resource.


The Python Programming Language: Functions


In [1]:
x = 1
y = 2
x + y


Out[1]:
3

In [2]:
x


Out[2]:
1


add_numbers is a function that takes two numbers and adds them together.


In [3]:
def add_numbers(x, y):
    return x + y

add_numbers(x, y)


Out[3]:
3


add_numbers updated to take an optional 3rd parameter. Using print allows printing of multiple expressions within a single cell.


In [4]:
def add_numbers(x,y,z=None):
    if (z==None):
        return x+y
    else:
        return x+y+z

print(add_numbers(1, 2))
print(add_numbers(1, 2, 3))


3
6


add_numbers updated to take an optional flag parameter.


In [5]:
def add_numbers(x, y, z=None, flag=False):
    if (flag):
        print('Flag is true!')
    if (z==None):
        return x + y
    else:
        return x + y + z
    
print(add_numbers(1, 2, flag=True))


Flag is true!
3


Assign function add_numbers to variable a.


In [6]:
def add_numbers(x,y):
    return x+y

a = add_numbers
a(1,2)


Out[6]:
3


The Python Programming Language: Types and Sequences


Use type to return the object's type.


In [1]:
type('This is a string')


Out[1]:
str

In [2]:
type(None)


Out[2]:
NoneType

In [3]:
type(1)


Out[3]:
int

In [4]:
type(1.0)


Out[4]:
float

In [7]:
type(add_numbers)


Out[7]:
function


Tuples are an immutable data structure (cannot be altered).


In [8]:
x = (1, 'a', 2, 'b')
type(x)


Out[8]:
tuple


Lists are a mutable data structure.


In [9]:
x = [1, 'a', 2, 'b']
type(x)


Out[9]:
list


Use append to append an object to a list.


In [10]:
x.append(3.3)
print(x)


[1, 'a', 2, 'b', 3.3]


This is an example of how to loop through each item in the list.


In [11]:
for item in x:
    print(item)


1
a
2
b
3.3


Or using the indexing operator:


In [12]:
i=0
while( i != len(x) ):
    print(x[i])
    i = i + 1


1
a
2
b
3.3


Use + to concatenate lists.


In [13]:
[1,2] + [3,4]


Out[13]:
[1, 2, 3, 4]


Use * to repeat lists.


In [14]:
[1]*3


Out[14]:
[1, 1, 1]


Use the in operator to check if something is inside a list.


In [15]:
1 in [1, 2, 3]


Out[15]:
True


Now let's look at strings. Use bracket notation to slice a string.


In [18]:
x = 'This is a string'
print(x[0]) #first character
print(x[0:1]) #first character, but we have explicitly set the end character
print(x[0:2]) #first two characters
print(x[::-1])


T
T
Th
gnirts a si sihT


This will return the last element of the string.


In [19]:
x[-1]


Out[19]:
'g'


This will return the slice starting from the 4th element from the end and stopping before the 2nd element from the end.


In [20]:
x[-4:-2]


Out[20]:
'ri'


This is a slice from the beginning of the string and stopping before the 3rd element.


In [21]:
x[:3]


Out[21]:
'Thi'


And this is a slice starting from the 3rd element of the string and going all the way to the end.


In [22]:
x[3:]


Out[22]:
's is a string'

In [23]:
firstname = 'Christopher'
lastname = 'Brooks'

print(firstname + ' ' + lastname)
print(firstname*3)
print('Chris' in firstname)


Christopher Brooks
ChristopherChristopherChristopher
True


split returns a list of all the words in a string, or a list split on a specific character.


In [24]:
firstname = 'Christopher Arthur Hansen Brooks'.split(' ')[0] # [0] selects the first element of the list
lastname = 'Christopher Arthur Hansen Brooks'.split(' ')[-1] # [-1] selects the last element of the list
print(firstname)
print(lastname)


Christopher
Brooks


Make sure you convert objects to strings before concatenating.


In [25]:
'Chris' + 2


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-25-1623ac76de6e> in <module>()
----> 1 'Chris' + 2

TypeError: Can't convert 'int' object to str implicitly

In [26]:
'Chris' + str(2)


Out[26]:
'Chris2'


Dictionaries associate keys with values.


In [27]:
x = {'Christopher Brooks': 'brooksch@umich.edu', 'Bill Gates': 'billg@microsoft.com'}
x['Christopher Brooks'] # Retrieve a value by using the indexing operator


Out[27]:
'brooksch@umich.edu'

In [29]:
x['Kevyn Collins-Thompson'] = "Test Test"
x['Kevyn Collins-Thompson']


Out[29]:
'Test Test'


Iterate over all of the keys:


In [30]:
for name in x:
    print(x[name])


Test Test
billg@microsoft.com
brooksch@umich.edu


Iterate over all of the values:


In [36]:
for email in x.values():
    print(email)


Test Test
billg@microsoft.com
brooksch@umich.edu


Iterate over all of the items in the list:


In [37]:
for name, email in x.items():
    print(name)
    print(email)


Kevyn Collins-Thompson
Test Test
Bill Gates
billg@microsoft.com
Christopher Brooks
brooksch@umich.edu


You can unpack a sequence into different variables:


In [38]:
x = ('Christopher', 'Brooks', 'brooksch@umich.edu')
fname, lname, email = x

In [39]:
fname


Out[39]:
'Christopher'

In [40]:
lname


Out[40]:
'Brooks'


Make sure the number of values you are unpacking matches the number of variables being assigned.


In [42]:
x = ('Christopher', 'Brooks', 'brooksch@umich.edu', 'Ann Arbor')
fname, lname, email, location = x


The Python Programming Language: More on Strings


In [47]:
print("Chris" + 2)


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-47-c2c461037565> in <module>()
----> 1 print("Chris" + 2)

TypeError: Can't convert 'int' object to str implicitly

In [48]:
print('Chris' + str(2))


Chris2


Python has a built in method for convenient string formatting.


In [49]:
sales_record = {
'price': 3.24,
'num_items': 4,
'person': 'Chris'}

sales_statement = '{} bought {} item(s) at a price of {} each for a total of {}'

print(sales_statement.format(sales_record['person'],
                             sales_record['num_items'],
                             sales_record['price'],
                             sales_record['num_items']*sales_record['price']))


Chris bought 4 item(s) at a price of 3.24 each for a total of 12.96


Reading and Writing CSV files


Let's import our datafile mpg.csv, which contains fuel economy data for 234 cars.

  • mpg : miles per gallon
  • class : car classification
  • cty : city mpg
  • cyl : # of cylinders
  • displ : engine displacement in liters
  • drv : f = front-wheel drive, r = rear wheel drive, 4 = 4wd
  • fl : fuel (e = ethanol E85, d = diesel, r = regular, p = premium, c = CNG)
  • hwy : highway mpg
  • manufacturer : automobile manufacturer
  • model : model of car
  • trans : type of transmission
  • year : model year

In [52]:
import csv
import pandas as pd

# Nice, sets decimple point
%precision 2

with open('mpg.csv') as csvfile:
    mpg = list(csv.DictReader(csvfile))

df = pd.read_csv('mpg.csv')
    
mpg[:3] # The first three dictionaries in our list.
df


Out[52]:
Unnamed: 0 manufacturer model displ year cyl trans drv cty hwy fl class
0 1 audi a4 1.8 1999 4 auto(l5) f 18 29 p compact
1 2 audi a4 1.8 1999 4 manual(m5) f 21 29 p compact
2 3 audi a4 2.0 2008 4 manual(m6) f 20 31 p compact
3 4 audi a4 2.0 2008 4 auto(av) f 21 30 p compact
4 5 audi a4 2.8 1999 6 auto(l5) f 16 26 p compact
5 6 audi a4 2.8 1999 6 manual(m5) f 18 26 p compact
6 7 audi a4 3.1 2008 6 auto(av) f 18 27 p compact
7 8 audi a4 quattro 1.8 1999 4 manual(m5) 4 18 26 p compact
8 9 audi a4 quattro 1.8 1999 4 auto(l5) 4 16 25 p compact
9 10 audi a4 quattro 2.0 2008 4 manual(m6) 4 20 28 p compact
10 11 audi a4 quattro 2.0 2008 4 auto(s6) 4 19 27 p compact
11 12 audi a4 quattro 2.8 1999 6 auto(l5) 4 15 25 p compact
12 13 audi a4 quattro 2.8 1999 6 manual(m5) 4 17 25 p compact
13 14 audi a4 quattro 3.1 2008 6 auto(s6) 4 17 25 p compact
14 15 audi a4 quattro 3.1 2008 6 manual(m6) 4 15 25 p compact
15 16 audi a6 quattro 2.8 1999 6 auto(l5) 4 15 24 p midsize
16 17 audi a6 quattro 3.1 2008 6 auto(s6) 4 17 25 p midsize
17 18 audi a6 quattro 4.2 2008 8 auto(s6) 4 16 23 p midsize
18 19 chevrolet c1500 suburban 2wd 5.3 2008 8 auto(l4) r 14 20 r suv
19 20 chevrolet c1500 suburban 2wd 5.3 2008 8 auto(l4) r 11 15 e suv
20 21 chevrolet c1500 suburban 2wd 5.3 2008 8 auto(l4) r 14 20 r suv
21 22 chevrolet c1500 suburban 2wd 5.7 1999 8 auto(l4) r 13 17 r suv
22 23 chevrolet c1500 suburban 2wd 6.0 2008 8 auto(l4) r 12 17 r suv
23 24 chevrolet corvette 5.7 1999 8 manual(m6) r 16 26 p 2seater
24 25 chevrolet corvette 5.7 1999 8 auto(l4) r 15 23 p 2seater
25 26 chevrolet corvette 6.2 2008 8 manual(m6) r 16 26 p 2seater
26 27 chevrolet corvette 6.2 2008 8 auto(s6) r 15 25 p 2seater
27 28 chevrolet corvette 7.0 2008 8 manual(m6) r 15 24 p 2seater
28 29 chevrolet k1500 tahoe 4wd 5.3 2008 8 auto(l4) 4 14 19 r suv
29 30 chevrolet k1500 tahoe 4wd 5.3 2008 8 auto(l4) 4 11 14 e suv
... ... ... ... ... ... ... ... ... ... ... ... ...
204 205 toyota toyota tacoma 4wd 3.4 1999 6 auto(l4) 4 15 19 r pickup
205 206 toyota toyota tacoma 4wd 4.0 2008 6 manual(m6) 4 15 18 r pickup
206 207 toyota toyota tacoma 4wd 4.0 2008 6 auto(l5) 4 16 20 r pickup
207 208 volkswagen gti 2.0 1999 4 manual(m5) f 21 29 r compact
208 209 volkswagen gti 2.0 1999 4 auto(l4) f 19 26 r compact
209 210 volkswagen gti 2.0 2008 4 manual(m6) f 21 29 p compact
210 211 volkswagen gti 2.0 2008 4 auto(s6) f 22 29 p compact
211 212 volkswagen gti 2.8 1999 6 manual(m5) f 17 24 r compact
212 213 volkswagen jetta 1.9 1999 4 manual(m5) f 33 44 d compact
213 214 volkswagen jetta 2.0 1999 4 manual(m5) f 21 29 r compact
214 215 volkswagen jetta 2.0 1999 4 auto(l4) f 19 26 r compact
215 216 volkswagen jetta 2.0 2008 4 auto(s6) f 22 29 p compact
216 217 volkswagen jetta 2.0 2008 4 manual(m6) f 21 29 p compact
217 218 volkswagen jetta 2.5 2008 5 auto(s6) f 21 29 r compact
218 219 volkswagen jetta 2.5 2008 5 manual(m5) f 21 29 r compact
219 220 volkswagen jetta 2.8 1999 6 auto(l4) f 16 23 r compact
220 221 volkswagen jetta 2.8 1999 6 manual(m5) f 17 24 r compact
221 222 volkswagen new beetle 1.9 1999 4 manual(m5) f 35 44 d subcompact
222 223 volkswagen new beetle 1.9 1999 4 auto(l4) f 29 41 d subcompact
223 224 volkswagen new beetle 2.0 1999 4 manual(m5) f 21 29 r subcompact
224 225 volkswagen new beetle 2.0 1999 4 auto(l4) f 19 26 r subcompact
225 226 volkswagen new beetle 2.5 2008 5 manual(m5) f 20 28 r subcompact
226 227 volkswagen new beetle 2.5 2008 5 auto(s6) f 20 29 r subcompact
227 228 volkswagen passat 1.8 1999 4 manual(m5) f 21 29 p midsize
228 229 volkswagen passat 1.8 1999 4 auto(l5) f 18 29 p midsize
229 230 volkswagen passat 2.0 2008 4 auto(s6) f 19 28 p midsize
230 231 volkswagen passat 2.0 2008 4 manual(m6) f 21 29 p midsize
231 232 volkswagen passat 2.8 1999 6 auto(l5) f 16 26 p midsize
232 233 volkswagen passat 2.8 1999 6 manual(m5) f 18 26 p midsize
233 234 volkswagen passat 3.6 2008 6 auto(s6) f 17 26 p midsize

234 rows × 12 columns


csv.Dictreader has read in each row of our csv file as a dictionary. len shows that our list is comprised of 234 dictionaries.


In [53]:
len(mpg)


Out[53]:
234


keys gives us the column names of our csv.


In [54]:
mpg[0].keys()


Out[54]:
dict_keys(['', 'trans', 'manufacturer', 'hwy', 'fl', 'displ', 'cyl', 'model', 'class', 'cty', 'drv', 'year'])


This is how to find the average cty fuel economy across all cars. All values in the dictionaries are strings, so we need to convert to float.


In [55]:
sum(float(d['cty']) for d in mpg) / len(mpg)


Out[55]:
16.86


Similarly this is how to find the average hwy fuel economy across all cars.


In [56]:
sum(float(d['hwy']) for d in mpg) / len(mpg)


Out[56]:
23.44


Use set to return the unique values for the number of cylinders the cars in our dataset have.


In [58]:
# set returns unique values
cylinders = set(d['cyl'] for d in mpg)
cylinders


Out[58]:
{'4', '5', '6', '8'}


Here's a more complex example where we are grouping the cars by number of cylinder, and finding the average cty mpg for each group.


In [59]:
CtyMpgByCyl = []

for c in cylinders: # iterate over all the cylinder levels
    summpg = 0
    cyltypecount = 0
    for d in mpg: # iterate over all dictionaries
        if d['cyl'] == c: # if the cylinder level type matches,
            summpg += float(d['cty']) # add the cty mpg
            cyltypecount += 1 # increment the count
    CtyMpgByCyl.append((c, summpg / cyltypecount)) # append the tuple ('cylinder', 'avg mpg')

CtyMpgByCyl.sort(key=lambda x: x[0])
CtyMpgByCyl


Out[59]:
[('4', 21.01), ('5', 20.50), ('6', 16.22), ('8', 12.57)]


Use set to return the unique values for the class types in our dataset.


In [60]:
vehicleclass = set(d['class'] for d in mpg) # what are the class types
vehicleclass


Out[60]:
{'2seater', 'compact', 'midsize', 'minivan', 'pickup', 'subcompact', 'suv'}


And here's an example of how to find the average hwy mpg for each class of vehicle in our dataset.


In [61]:
HwyMpgByClass = []

for t in vehicleclass: # iterate over all the vehicle classes
    summpg = 0
    vclasscount = 0
    for d in mpg: # iterate over all dictionaries
        if d['class'] == t: # if the cylinder amount type matches,
            summpg += float(d['hwy']) # add the hwy mpg
            vclasscount += 1 # increment the count
    HwyMpgByClass.append((t, summpg / vclasscount)) # append the tuple ('class', 'avg mpg')

HwyMpgByClass.sort(key=lambda x: x[1])
HwyMpgByClass


Out[61]:
[('pickup', 16.88),
 ('suv', 18.13),
 ('minivan', 22.36),
 ('2seater', 24.80),
 ('midsize', 27.29),
 ('subcompact', 28.14),
 ('compact', 28.30)]


The Python Programming Language: Dates and Times


In [62]:
import datetime as dt
import time as tm


time returns the current time in seconds since the Epoch. (January 1st, 1970)


In [63]:
tm.time()


Out[63]:
1484596690.50


Convert the timestamp to datetime.


In [64]:
dtnow = dt.datetime.fromtimestamp(tm.time())
dtnow


Out[64]:
datetime.datetime(2017, 1, 16, 19, 58, 33, 790718)


Handy datetime attributes:


In [65]:
dtnow.year, dtnow.month, dtnow.day, dtnow.hour, dtnow.minute, dtnow.second # get year, month, day, etc.from a datetime


Out[65]:
(2017, 1, 16, 19, 58, 33)


timedelta is a duration expressing the difference between two dates.


In [66]:
delta = dt.timedelta(days = 100) # create a timedelta of 100 days
delta


Out[66]:
datetime.timedelta(100)

In [71]:
dt.date.today()


Out[71]:
datetime.date(2017, 1, 16)


date.today returns the current local date.


In [68]:
today = dt.date.today()

In [69]:
today - delta # the date 100 days ago


Out[69]:
datetime.date(2016, 10, 8)

In [70]:
today > today-delta # compare dates


Out[70]:
True


The Python Programming Language: Objects and map()


An example of a class in python:


In [1]:
class Person:
    department = 'School of Information' #a class variable

    def set_name(self, new_name): #a method
        self.name = new_name
    def set_location(self, new_location):
        self.location = new_location

In [2]:
person = Person()
person.set_name('Christopher Brooks')
person.set_location('Ann Arbor, MI, USA')
print('{} live in {} and works in the department {}'.format(person.name, person.location, person.department))


Christopher Brooks live in Ann Arbor, MI, USA and works in the department School of Information


Here's an example of mapping the min function between two lists.


In [27]:
store1 = [10.00, 11.00, 12.34, 2.34]
store2 = [9.00, 11.10, 12.34, 2.01]
cheapest = map(min, store1, store2)
cheapest


Out[27]:
<map at 0x7fd72c8d3860>


Now let's iterate through the map object to see the values.


In [28]:
for item in cheapest:
    print (item)


9.0
11.0
12.34
2.01

In [22]:
people = ['Dr. Christopher Brooks', 'Dr. Kevyn Collins-Thompson', 'Dr. VG Vinod Vydiswaran', 'Dr. Daniel Romero']

def split_title_and_name(person):
  title = person.split(' ')[0]
  lname = person.split(' ')[-1]
  return title +" "+ lname

list(map(split_title_and_name, people))


Out[22]:
['Dr. Brooks', 'Dr. Collins-Thompson', 'Dr. Vydiswaran', 'Dr. Romero']


The Python Programming Language: Lambda and List Comprehensions


Here's an example of lambda that takes in three parameters and adds the first two.


In [29]:
# Single function only
my_function = lambda a, b, c : a + b + c

In [30]:
my_function(1, 2, 3)


Out[30]:
6

In [31]:
people = ['Dr. Christopher Brooks', 'Dr. Kevyn Collins-Thompson', 'Dr. VG Vinod Vydiswaran', 'Dr. Daniel Romero']

def split_title_and_name(person):
    return person.split()[0] + ' ' + person.split()[-1]

#option 1
for person in people:
    print(split_title_and_name(person) == (lambda x: x.split()[0] + ' ' + x.split()[-1])(person))

#option 2
list(map(split_title_and_name, people)) == list(map(lambda person: person.split()[0] + ' ' + person.split()[-1], people))


True
True
True
True
Out[31]:
True


Let's iterate from 0 to 999 and return the even numbers.


In [32]:
my_list = []
for number in range(0, 1000):
    if number % 2 == 0:
        my_list.append(number)
my_list


Out[32]:
[0,
 2,
 4,
 6,
 8,
 10,
 12,
 14,
 16,
 18,
 20,
 22,
 24,
 26,
 28,
 30,
 32,
 34,
 36,
 38,
 40,
 42,
 44,
 46,
 48,
 50,
 52,
 54,
 56,
 58,
 60,
 62,
 64,
 66,
 68,
 70,
 72,
 74,
 76,
 78,
 80,
 82,
 84,
 86,
 88,
 90,
 92,
 94,
 96,
 98,
 100,
 102,
 104,
 106,
 108,
 110,
 112,
 114,
 116,
 118,
 120,
 122,
 124,
 126,
 128,
 130,
 132,
 134,
 136,
 138,
 140,
 142,
 144,
 146,
 148,
 150,
 152,
 154,
 156,
 158,
 160,
 162,
 164,
 166,
 168,
 170,
 172,
 174,
 176,
 178,
 180,
 182,
 184,
 186,
 188,
 190,
 192,
 194,
 196,
 198,
 200,
 202,
 204,
 206,
 208,
 210,
 212,
 214,
 216,
 218,
 220,
 222,
 224,
 226,
 228,
 230,
 232,
 234,
 236,
 238,
 240,
 242,
 244,
 246,
 248,
 250,
 252,
 254,
 256,
 258,
 260,
 262,
 264,
 266,
 268,
 270,
 272,
 274,
 276,
 278,
 280,
 282,
 284,
 286,
 288,
 290,
 292,
 294,
 296,
 298,
 300,
 302,
 304,
 306,
 308,
 310,
 312,
 314,
 316,
 318,
 320,
 322,
 324,
 326,
 328,
 330,
 332,
 334,
 336,
 338,
 340,
 342,
 344,
 346,
 348,
 350,
 352,
 354,
 356,
 358,
 360,
 362,
 364,
 366,
 368,
 370,
 372,
 374,
 376,
 378,
 380,
 382,
 384,
 386,
 388,
 390,
 392,
 394,
 396,
 398,
 400,
 402,
 404,
 406,
 408,
 410,
 412,
 414,
 416,
 418,
 420,
 422,
 424,
 426,
 428,
 430,
 432,
 434,
 436,
 438,
 440,
 442,
 444,
 446,
 448,
 450,
 452,
 454,
 456,
 458,
 460,
 462,
 464,
 466,
 468,
 470,
 472,
 474,
 476,
 478,
 480,
 482,
 484,
 486,
 488,
 490,
 492,
 494,
 496,
 498,
 500,
 502,
 504,
 506,
 508,
 510,
 512,
 514,
 516,
 518,
 520,
 522,
 524,
 526,
 528,
 530,
 532,
 534,
 536,
 538,
 540,
 542,
 544,
 546,
 548,
 550,
 552,
 554,
 556,
 558,
 560,
 562,
 564,
 566,
 568,
 570,
 572,
 574,
 576,
 578,
 580,
 582,
 584,
 586,
 588,
 590,
 592,
 594,
 596,
 598,
 600,
 602,
 604,
 606,
 608,
 610,
 612,
 614,
 616,
 618,
 620,
 622,
 624,
 626,
 628,
 630,
 632,
 634,
 636,
 638,
 640,
 642,
 644,
 646,
 648,
 650,
 652,
 654,
 656,
 658,
 660,
 662,
 664,
 666,
 668,
 670,
 672,
 674,
 676,
 678,
 680,
 682,
 684,
 686,
 688,
 690,
 692,
 694,
 696,
 698,
 700,
 702,
 704,
 706,
 708,
 710,
 712,
 714,
 716,
 718,
 720,
 722,
 724,
 726,
 728,
 730,
 732,
 734,
 736,
 738,
 740,
 742,
 744,
 746,
 748,
 750,
 752,
 754,
 756,
 758,
 760,
 762,
 764,
 766,
 768,
 770,
 772,
 774,
 776,
 778,
 780,
 782,
 784,
 786,
 788,
 790,
 792,
 794,
 796,
 798,
 800,
 802,
 804,
 806,
 808,
 810,
 812,
 814,
 816,
 818,
 820,
 822,
 824,
 826,
 828,
 830,
 832,
 834,
 836,
 838,
 840,
 842,
 844,
 846,
 848,
 850,
 852,
 854,
 856,
 858,
 860,
 862,
 864,
 866,
 868,
 870,
 872,
 874,
 876,
 878,
 880,
 882,
 884,
 886,
 888,
 890,
 892,
 894,
 896,
 898,
 900,
 902,
 904,
 906,
 908,
 910,
 912,
 914,
 916,
 918,
 920,
 922,
 924,
 926,
 928,
 930,
 932,
 934,
 936,
 938,
 940,
 942,
 944,
 946,
 948,
 950,
 952,
 954,
 956,
 958,
 960,
 962,
 964,
 966,
 968,
 970,
 972,
 974,
 976,
 978,
 980,
 982,
 984,
 986,
 988,
 990,
 992,
 994,
 996,
 998]


Now the same thing but with list comprehension.


In [33]:
my_list = [number for number in range(0,1000) if number % 2 == 0]
my_list


Out[33]:
[0,
 2,
 4,
 6,
 8,
 10,
 12,
 14,
 16,
 18,
 20,
 22,
 24,
 26,
 28,
 30,
 32,
 34,
 36,
 38,
 40,
 42,
 44,
 46,
 48,
 50,
 52,
 54,
 56,
 58,
 60,
 62,
 64,
 66,
 68,
 70,
 72,
 74,
 76,
 78,
 80,
 82,
 84,
 86,
 88,
 90,
 92,
 94,
 96,
 98,
 100,
 102,
 104,
 106,
 108,
 110,
 112,
 114,
 116,
 118,
 120,
 122,
 124,
 126,
 128,
 130,
 132,
 134,
 136,
 138,
 140,
 142,
 144,
 146,
 148,
 150,
 152,
 154,
 156,
 158,
 160,
 162,
 164,
 166,
 168,
 170,
 172,
 174,
 176,
 178,
 180,
 182,
 184,
 186,
 188,
 190,
 192,
 194,
 196,
 198,
 200,
 202,
 204,
 206,
 208,
 210,
 212,
 214,
 216,
 218,
 220,
 222,
 224,
 226,
 228,
 230,
 232,
 234,
 236,
 238,
 240,
 242,
 244,
 246,
 248,
 250,
 252,
 254,
 256,
 258,
 260,
 262,
 264,
 266,
 268,
 270,
 272,
 274,
 276,
 278,
 280,
 282,
 284,
 286,
 288,
 290,
 292,
 294,
 296,
 298,
 300,
 302,
 304,
 306,
 308,
 310,
 312,
 314,
 316,
 318,
 320,
 322,
 324,
 326,
 328,
 330,
 332,
 334,
 336,
 338,
 340,
 342,
 344,
 346,
 348,
 350,
 352,
 354,
 356,
 358,
 360,
 362,
 364,
 366,
 368,
 370,
 372,
 374,
 376,
 378,
 380,
 382,
 384,
 386,
 388,
 390,
 392,
 394,
 396,
 398,
 400,
 402,
 404,
 406,
 408,
 410,
 412,
 414,
 416,
 418,
 420,
 422,
 424,
 426,
 428,
 430,
 432,
 434,
 436,
 438,
 440,
 442,
 444,
 446,
 448,
 450,
 452,
 454,
 456,
 458,
 460,
 462,
 464,
 466,
 468,
 470,
 472,
 474,
 476,
 478,
 480,
 482,
 484,
 486,
 488,
 490,
 492,
 494,
 496,
 498,
 500,
 502,
 504,
 506,
 508,
 510,
 512,
 514,
 516,
 518,
 520,
 522,
 524,
 526,
 528,
 530,
 532,
 534,
 536,
 538,
 540,
 542,
 544,
 546,
 548,
 550,
 552,
 554,
 556,
 558,
 560,
 562,
 564,
 566,
 568,
 570,
 572,
 574,
 576,
 578,
 580,
 582,
 584,
 586,
 588,
 590,
 592,
 594,
 596,
 598,
 600,
 602,
 604,
 606,
 608,
 610,
 612,
 614,
 616,
 618,
 620,
 622,
 624,
 626,
 628,
 630,
 632,
 634,
 636,
 638,
 640,
 642,
 644,
 646,
 648,
 650,
 652,
 654,
 656,
 658,
 660,
 662,
 664,
 666,
 668,
 670,
 672,
 674,
 676,
 678,
 680,
 682,
 684,
 686,
 688,
 690,
 692,
 694,
 696,
 698,
 700,
 702,
 704,
 706,
 708,
 710,
 712,
 714,
 716,
 718,
 720,
 722,
 724,
 726,
 728,
 730,
 732,
 734,
 736,
 738,
 740,
 742,
 744,
 746,
 748,
 750,
 752,
 754,
 756,
 758,
 760,
 762,
 764,
 766,
 768,
 770,
 772,
 774,
 776,
 778,
 780,
 782,
 784,
 786,
 788,
 790,
 792,
 794,
 796,
 798,
 800,
 802,
 804,
 806,
 808,
 810,
 812,
 814,
 816,
 818,
 820,
 822,
 824,
 826,
 828,
 830,
 832,
 834,
 836,
 838,
 840,
 842,
 844,
 846,
 848,
 850,
 852,
 854,
 856,
 858,
 860,
 862,
 864,
 866,
 868,
 870,
 872,
 874,
 876,
 878,
 880,
 882,
 884,
 886,
 888,
 890,
 892,
 894,
 896,
 898,
 900,
 902,
 904,
 906,
 908,
 910,
 912,
 914,
 916,
 918,
 920,
 922,
 924,
 926,
 928,
 930,
 932,
 934,
 936,
 938,
 940,
 942,
 944,
 946,
 948,
 950,
 952,
 954,
 956,
 958,
 960,
 962,
 964,
 966,
 968,
 970,
 972,
 974,
 976,
 978,
 980,
 982,
 984,
 986,
 988,
 990,
 992,
 994,
 996,
 998]

In [34]:
def times_tables():
    lst = []
    for i in range(10):
        for j in range (10):
            lst.append(i*j)
    return lst

times_tables() == [j*i for i in range(10) for j in range(10)]


Out[34]:
True

In [49]:
lowercase = 'abcdefghijklmnopqrstuvwxyz'
digits = '0123456789'
    
correct_answer = [a+b+c+d for a in lowercase for b in lowercase for c in digits for d in digits]

In [50]:
correct_answer[0:100]


Out[50]:
['aa00',
 'aa01',
 'aa02',
 'aa03',
 'aa04',
 'aa05',
 'aa06',
 'aa07',
 'aa08',
 'aa09',
 'aa10',
 'aa11',
 'aa12',
 'aa13',
 'aa14',
 'aa15',
 'aa16',
 'aa17',
 'aa18',
 'aa19',
 'aa20',
 'aa21',
 'aa22',
 'aa23',
 'aa24',
 'aa25',
 'aa26',
 'aa27',
 'aa28',
 'aa29',
 'aa30',
 'aa31',
 'aa32',
 'aa33',
 'aa34',
 'aa35',
 'aa36',
 'aa37',
 'aa38',
 'aa39',
 'aa40',
 'aa41',
 'aa42',
 'aa43',
 'aa44',
 'aa45',
 'aa46',
 'aa47',
 'aa48',
 'aa49',
 'aa50',
 'aa51',
 'aa52',
 'aa53',
 'aa54',
 'aa55',
 'aa56',
 'aa57',
 'aa58',
 'aa59',
 'aa60',
 'aa61',
 'aa62',
 'aa63',
 'aa64',
 'aa65',
 'aa66',
 'aa67',
 'aa68',
 'aa69',
 'aa70',
 'aa71',
 'aa72',
 'aa73',
 'aa74',
 'aa75',
 'aa76',
 'aa77',
 'aa78',
 'aa79',
 'aa80',
 'aa81',
 'aa82',
 'aa83',
 'aa84',
 'aa85',
 'aa86',
 'aa87',
 'aa88',
 'aa89',
 'aa90',
 'aa91',
 'aa92',
 'aa93',
 'aa94',
 'aa95',
 'aa96',
 'aa97',
 'aa98',
 'aa99']


The Python Programming Language: Numerical Python (NumPy)


In [ ]:
import numpy as np


Creating Arrays

Create a list and convert it to a numpy array


In [ ]:
mylist = [1, 2, 3]
x = np.array(mylist)
x


Or just pass in a list directly


In [ ]:
y = np.array([4, 5, 6])
y


Pass in a list of lists to create a multidimensional array.


In [ ]:
m = np.array([[7, 8, 9], [10, 11, 12]])
m


Use the shape method to find the dimensions of the array. (rows, columns)


In [ ]:
m.shape


arange returns evenly spaced values within a given interval.


In [ ]:
n = np.arange(0, 30, 2) # start at 0 count up by 2, stop before 30
n


reshape returns an array with the same data with a new shape.


In [ ]:
n = n.reshape(3, 5) # reshape array to be 3x5
n


linspace returns evenly spaced numbers over a specified interval.


In [ ]:
o = np.linspace(0, 4, 9) # return 9 evenly spaced values from 0 to 4
o


resize changes the shape and size of array in-place.


In [ ]:
o.resize(3, 3)
o


ones returns a new array of given shape and type, filled with ones.


In [ ]:
np.ones((3, 2))


zeros returns a new array of given shape and type, filled with zeros.


In [ ]:
np.zeros((2, 3))


eye returns a 2-D array with ones on the diagonal and zeros elsewhere.


In [ ]:
np.eye(3)


diag extracts a diagonal or constructs a diagonal array.


In [ ]:
np.diag(y)


Create an array using repeating list (or see np.tile)


In [ ]:
np.array([1, 2, 3] * 3)


Repeat elements of an array using repeat.


In [ ]:
np.repeat([1, 2, 3], 3)


Combining Arrays


In [ ]:
p = np.ones([2, 3], int)
p


Use vstack to stack arrays in sequence vertically (row wise).


In [ ]:
np.vstack([p, 2*p])


Use hstack to stack arrays in sequence horizontally (column wise).


In [ ]:
np.hstack([p, 2*p])


Operations

Use +, -, *, / and ** to perform element wise addition, subtraction, multiplication, division and power.


In [ ]:
print(x + y) # elementwise addition     [1 2 3] + [4 5 6] = [5  7  9]
print(x - y) # elementwise subtraction  [1 2 3] - [4 5 6] = [-3 -3 -3]

In [ ]:
print(x * y) # elementwise multiplication  [1 2 3] * [4 5 6] = [4  10  18]
print(x / y) # elementwise divison         [1 2 3] / [4 5 6] = [0.25  0.4  0.5]

In [ ]:
print(x**2) # elementwise power  [1 2 3] ^2 =  [1 4 9]


Dot Product:

$ \begin{bmatrix}x_1 \ x_2 \ x_3\end{bmatrix} \cdot \begin{bmatrix}y_1 \\ y_2 \\ y_3\end{bmatrix} = x_1 y_1 + x_2 y_2 + x_3 y_3$


In [ ]:
x.dot(y) # dot product  1*4 + 2*5 + 3*6

In [ ]:
z = np.array([y, y**2])
print(len(z)) # number of rows of array


Let's look at transposing arrays. Transposing permutes the dimensions of the array.


In [ ]:
z = np.array([y, y**2])
z


The shape of array z is (2,3) before transposing.


In [ ]:
z.shape


Use .T to get the transpose.


In [ ]:
z.T


The number of rows has swapped with the number of columns.


In [ ]:
z.T.shape


Use .dtype to see the data type of the elements in the array.


In [ ]:
z.dtype


Use .astype to cast to a specific type.


In [ ]:
z = z.astype('f')
z.dtype


Math Functions

Numpy has many built in math functions that can be performed on arrays.


In [ ]:
a = np.array([-4, -2, 1, 3, 5])

In [ ]:
a.sum()

In [ ]:
a.max()

In [ ]:
a.min()

In [ ]:
a.mean()

In [ ]:
a.std()


argmax and argmin return the index of the maximum and minimum values in the array.


In [ ]:
a.argmax()

In [ ]:
a.argmin()


Indexing / Slicing


In [ ]:
s = np.arange(13)**2
s


Use bracket notation to get the value at a specific index. Remember that indexing starts at 0.


In [ ]:
s[0], s[4], s[-1]


Use : to indicate a range. array[start:stop]

Leaving start or stop empty will default to the beginning/end of the array.


In [ ]:
s[1:5]


Use negatives to count from the back.


In [ ]:
s[-4:]


A second : can be used to indicate step-size. array[start:stop:stepsize]

Here we are starting 5th element from the end, and counting backwards by 2 until the beginning of the array is reached.


In [ ]:
s[-5::-2]


Let's look at a multidimensional array.


In [ ]:
r = np.arange(36)
r.resize((6, 6))
r


Use bracket notation to slice: array[row, column]


In [ ]:
r[2, 2]


And use : to select a range of rows or columns


In [ ]:
r[3, 3:6]


Here we are selecting all the rows up to (and not including) row 2, and all the columns up to (and not including) the last column.


In [ ]:
r[:2, :-1]


This is a slice of the last row, and only every other element.


In [ ]:
r[-1, ::2]


We can also perform conditional indexing. Here we are selecting values from the array that are greater than 30. (Also see np.where)


In [ ]:
r[r > 30]


Here we are assigning all values in the array that are greater than 30 to the value of 30.


In [ ]:
r[r > 30] = 30
r


Copying Data

Be careful with copying and modifying arrays in NumPy!

r2 is a slice of r


In [ ]:
r2 = r[:3,:3]
r2


Set this slice's values to zero ([:] selects the entire array)


In [ ]:
r2[:] = 0
r2


r has also been changed!


In [ ]:
r


To avoid this, use r.copy to create a copy that will not affect the original array


In [ ]:
r_copy = r.copy()
r_copy


Now when r_copy is modified, r will not be changed.


In [ ]:
r_copy[:] = 10
print(r_copy, '\n')
print(r)


Iterating Over Arrays

Let's create a new 4 by 3 array of random numbers 0-9.


In [ ]:
test = np.random.randint(0, 10, (4,3))
test


Iterate by row:


In [ ]:
for row in test:
    print(row)


Iterate by index:


In [ ]:
for i in range(len(test)):
    print(test[i])


Iterate by row and index:


In [ ]:
for i, row in enumerate(test):
    print('row', i, 'is', row)


Use zip to iterate over multiple iterables.


In [ ]:
test2 = test**2
test2

In [ ]:
for i, j in zip(test, test2):
    print(i,'+',j,'=',i+j)