Lesson 10: Functional Programming
Pragmatic AI Labs
This notebook was produced by Pragmatic AI Labs. You can continue learning about these topics by:
- Buying a copy of Pragmatic AI: An Introduction to Cloud-Based Machine Learning
- Reading an online copy of Pragmatic AI:Pragmatic AI: An Introduction to Cloud-Based Machine Learning
- Watching video Essential Machine Learning and AI with Python and Jupyter Notebook-Video-SafariOnline on Safari Books Online.
- Watching video AWS Certified Machine Learning-Speciality
- Purchasing video Essential Machine Learning and AI with Python and Jupyter Notebook- Purchase Video
- Viewing more content at noahgift.com
10.1 Understand functional programming
Depending on state
wind = 'Southeast'
def describe_the_wind():
return f'The wind blows from the {wind}'
describe_the_wind()
'The wind blows from the Southeast'
Functional approach
def describe_the_wind(wind):
return f'The wind blows from the {wind}'
describe_the_wind('Northeast')
'The wind blows from the Northeast'
Changing state
WINDS = ['Northeast', 'Northwest', 'Southeast', 'Southwest']
WIND = WINDS[0]
def change_wind():
global WIND
WIND = WINDS[(WINDS.index(WIND) + 1)%3]
WIND
'Northeast'
change_wind()
WIND
'Northeast'
for _ in WINDS:
print(WIND)
change_wind()
Functional approach
def change_wind(wind_index):
winds = ['Northeast', 'Northwest', 'Southeast', 'Southwest']
return winds[wind_index]
print( change_wind(0) )
print( change_wind(1) )
print( change_wind(2) )
print( change_wind(3) )
Northeast
Northwest
Southeast
Southwest
Changing state
def change_mutable_data(data):
'''A function which changes
mutable data.'''
data['owner'] = 'White Star Line'
d = {"vehicle": "ship", "owner": "Joseph Bruce Ismay"}
change_mutable_data(d)
d
{'owner': 'White Star Line', 'vehicle': 'ship'}
Functional approach
d = {"vehicle": "ship", "owner": "Joseph Bruce Ismay"}
def change_owner(data):
new_data = data.copy()
new_data['owner'] = 'White Star Line'
return new_data
changed = change_owner(d)
changed
{'owner': 'White Star Line', 'vehicle': 'ship'}
10.2 Apply functions to data science workflows
import pandas as pd
moby_dick_quotes = [
"""It is not down on any map; true places never are.""",
"""
Consider the subtleness of the sea; how its most dreaded creatures glide under water, unapparent for the most part, and treacherously hidden beneath the loveliest tints of azure. Consider also the devilish brilliance and beauty of many of its most remorseless tribes, as the dainty embellished shape of many species of sharks. Consider, once more, the universal cannibalism of the sea; all whose creatures prey upon each other, carrying on eternal war since the world began.
Consider all this; and then turn to the green, gentle, and most docile earth; consider them both, the sea and the land; and do you not find a strange analogy to something in yourself? For as this appalling ocean surrounds the verdant land, so in the soul of man there lies one insular Tahiti, full of peace and joy, but encompassed by all the horrors of the half-known life. God keep thee! Push not off from that isle, thou canst never return!
""",
"""
The sea had jeeringly kept his finite body up, but drowned the infinite of his soul. Not drowned entirely, though. Rather carried down alive to wondrous depths, where strange shapes of the unwarped primal world glided to and fro before his passive eyes; and the miser-merman, Wisdom, revealed his hoarded heaps; and among the joyous, heartless, ever-juvenile eternities, Pip saw the multitudinous, God-omnipresent, coral insects, that out of the firmament of waters heaved the colossal orbs. He saw God’s foot upon the treadle of the loom, and spoke it; and therefore his shipmates called him mad. So man’s insanity is heaven’s sense; and wandering from all mortal reason, man comes at last to that celestial thought, which, to reason, is absurd and frantic; and weal or woe, feels then uncompromised, indifferent as his God.
"""
]
df = pd.DataFrame(moby_dick_quotes)
df.columns = ["quotes"]
df.head()
quotes | |
---|---|
0 | It is not down on any map; true places never are. |
1 | \n Consider the subtleness of the sea; how ... |
2 | \n The sea had jeeringly kept his finite bo... |
def classify_religious(column):
"""Creates Religion Feature"""
if "God" in column:
return "Religious"
return "Secular"
df["quote_type"] = df["quotes"].apply(classify_religious)
df.head()
quotes | quote_type | |
---|---|---|
0 | It is not down on any map; true places never are. | Secular |
1 | \n Consider the subtleness of the sea; how ... | Religious |
2 | \n The sea had jeeringly kept his finite bo... | Religious |
10.3 Use map/reduce/filter
map
def count_flower_petals(d):
return f"{d} petals counted so far"
counts = map(count_flower_petals, [0,1,2,3,4,5])
list(counts)
['0 petals counted so far',
'1 petals counted so far',
'2 petals counted so far',
'3 petals counted so far',
'4 petals counted so far',
'5 petals counted so far']
mapping with multiple inputs
l1 = [0,1,2,3,4]
l2 = [10,9,8,7,6]
def multi(d1, d2):
return d1 * d2
result = map(multi, l1, l2)
print( list(result) )
[0, 9, 16, 21, 24]
reduce
initial_balance = 10000
debits = [20, 40, 300, 3000, 1, 234]
balance = initial_balance
for debit in debits:
balance -= debit
balance
6405
inital_balance = 10000
debits = [20, 40, 300, 3000, 1, 234]
from functools import reduce
def minus(a, b):
return a - b
balance = reduce(minus, debits, initial_balance)
balance
6405
inital_balance = 10000
debits = [20, 40, 300, 3000, 1, 234]
from functools import reduce
import operator
print( reduce(operator.sub, debits, initial_balance) )
6405
filter
characters = ['C', 'b', 'c', 'A', 'b','P', 'g', 'S']
def cap(a):
return a.isupper()
retval = filter(cap, characters)
list(retval)
['C', 'A', 'P', 'S']
10.4 Use list comprehensions
For loop
names = ['tim', 'tiger', 'tabassum', 'theodora', 'tanya']
capd = []
for name in names:
capd.append(name.title())
capd
['Tim', 'Tiger', 'Tabassum', 'Theodora', 'Tanya']
Basic list comprehension
names = ['tim', 'tiger', 'tabassum', 'theodora', 'tanya']
capd = [x.title() for x in names]
capd
['Tim', 'Tiger', 'Tabassum', 'Theodora', 'Tanya']
Mapping
map example
def count_flower_petals(d):
return f"{d} petals counted so far"
counts = map(count_flower_petals, [0,1,2,3,4,5])
list(counts)
['0 petals counted so far',
'1 petals counted so far',
'2 petals counted so far',
'3 petals counted so far',
'4 petals counted so far',
'5 petals counted so far']
mapping using list comprehension
[f"{x} petals counted so far" for x in [0,1,2,3,4,5]]
['0 petals counted so far',
'1 petals counted so far',
'2 petals counted so far',
'3 petals counted so far',
'4 petals counted so far',
'5 petals counted so far']
Filtering
filter function
characters = ['C', 'b', 'c', 'A', 'b','P', 'g', 'S']
def cap(a):
return a.isupper()
retval = filter(cap, characters)
list(retval)
['C', 'A', 'P', 'S']
filtering in list comprehension
characters = ['C', 'b', 'c', 'A', 'b','P', 'g', 'S']
[x for x in characters if x.isupper()]
['C', 'A', 'P', 'S']
Multiple variables
horts = [ 32.0, 54.12, 12.4, 89.09]
verts = [ 15.9, -34.21, 45.54, 90]
[ f'x: {x} y: {y}' for x,y in zip(horts, verts) ]
['x: 32.0 y: 15.9', 'x: 54.12 y: -34.21', 'x: 12.4 y: 45.54', 'x: 89.09 y: 90']
list(zip(horts, verts))
[(32.0, 15.9), (54.12, -34.21), (12.4, 45.54), (89.09, 90)]
Flatten a list of lists
list_of_lists = [[1,2,3], [4,5,6], [7,8,9]]
[x for y in list_of_lists for x in y]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Nested
# Integers greater than and with 3 as a factor divided by 2
[y for y in range(20)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
[y for y in range(20) if y%3==0]
[0, 3, 6, 9, 12, 15, 18]
[x//2 for x in [y for y in range(20) if y%3==0] if x > 3]
[3, 4, 6, 7, 9]
10.5 Use dictionary comprehensions
rows = [{'name': 'barry', 'id': 1},
{'name': 'henry', 'id': 3},
{'name': 'suzy', 'id': 2}]
{ x['name']: x['id'] for x in rows}
{'barry': 1, 'henry': 3, 'suzy': 2}