Conditionals and Loops
Contents
Conditionals and Loops#
from datascience import *
from cs104 import *
import numpy as np
%matplotlib inline
Booleans and Comparison Operators#
3 > 1
True
type(3 > 1)
bool
3 = 3
Cell In[4], line 1
3 = 3
^
SyntaxError: cannot assign to literal
3 == 3
True
x = 5
y = 12
x == 7
False
y - x
7
4 < y - x <= 6
False
4 < y - x
True
y - x <= 6
False
True and False
False
True or False
True
True and True
True
Monopoly#
monopoly = Table().read_table("data/monopoly.csv")
monopoly
Name | Space | Color | Position | Price | PriceBuild | Rent | RentBuild1 | RentBuild2 | RentBuild3 | RentBuild4 | RentBuild5 | Number |
---|---|---|---|---|---|---|---|---|---|---|---|---|
Go | Go | nan | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Mediterranean Avenue | Street | Brown | 1 | 60 | 50 | 2 | 10 | 30 | 90 | 160 | 250 | 2 |
Community Chest | Chest | nan | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Baltic Avenue | Street | Brown | 3 | 60 | 50 | 4 | 20 | 60 | 180 | 320 | 450 | 2 |
Income Tax | Tax | nan | 4 | 200 | 0 | 200 | 0 | 0 | 0 | 0 | 0 | 0 |
Reading Railroad | Railroad | nan | 5 | 200 | 0 | 25 | 0 | 0 | 0 | 0 | 0 | 0 |
Oriental Avenue | Street | LightBlue | 6 | 100 | 50 | 6 | 30 | 90 | 270 | 400 | 550 | 3 |
Chance | Chance | nan | 7 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Vermont Avenue | Street | LightBlue | 8 | 100 | 50 | 6 | 30 | 90 | 270 | 400 | 550 | 3 |
Connecticut Avenue | Street | LightBlue | 9 | 120 | 50 | 8 | 40 | 100 | 300 | 450 | 600 | 3 |
... (30 rows omitted)
tiny_monopoly = monopoly.where('Color', are.not_equal_to('None'))
tiny_monopoly = tiny_monopoly.where('Space', are.containing('Street'))
tiny_monopoly = tiny_monopoly.select('Name', 'Color', 'Price')
tiny_monopoly = tiny_monopoly.sort('Name')
tiny_monopoly.show()
Name | Color | Price |
---|---|---|
Atlantic Avenue | Yellow | 260 |
Baltic Avenue | Brown | 60 |
Boardwalk | Blue | 400 |
Connecticut Avenue | LightBlue | 120 |
Illinois Avenue | Red | 240 |
Indiana Avenue | Red | 220 |
Kentucky Avenue | Red | 220 |
Marvin Gardens | Yellow | 280 |
Mediterranean Avenue | Brown | 60 |
New York Avenue | Orange | 200 |
North Carolina Avenue | Green | 300 |
Oriental Avenue | LightBlue | 100 |
Pacific Avenue | Green | 300 |
Park Place | Blue | 350 |
Pennsylvania Avenue | Green | 320 |
St. Charles Place | Pink | 140 |
St. James Place | Orange | 180 |
States Avenue | Pink | 140 |
Tennessee Avenue | Orange | 180 |
Ventnor Avenue | Yellow | 260 |
Vermont Avenue | LightBlue | 100 |
Virginia Avenue | Pink | 160 |
Suppose we only have 220 dollars. How many properties could we buy for exactly 220 dollars?
price = tiny_monopoly.column("Price")
price
array([260, 60, 400, 120, 240, 220, 220, 280, 60, 200, 300, 100, 300,
350, 320, 140, 180, 140, 180, 260, 100, 160])
price == 220
array([False, False, False, False, False, True, True, False, False,
False, False, False, False, False, False, False, False, False,
False, False, False, False])
sum(price==220)
2
np.count_nonzero(price == 220)
2
How many properties could we buy for less than or equal to 200 dollars?
price
array([260, 60, 400, 120, 240, 220, 220, 280, 60, 200, 300, 100, 300,
350, 320, 140, 180, 140, 180, 260, 100, 160])
price <= 200
array([False, True, False, True, False, False, False, False, True,
True, False, True, False, False, False, True, True, True,
True, False, True, True])
np.count_nonzero(price <= 200)
11
How many of the Monopoly spaces are light blue?
sum(monopoly.column("Color") == "LightBlue")
3
Conditional Statements#
def price_rating(price):
if price < 100:
print("Inexpensive")
price_rating(50)
Inexpensive
price_rating(500)
def price_rating(price):
if price < 100:
print("Inexpensive")
else:
print("Expensive")
price_rating(500)
Expensive
# return a value instead of printing
def price_rating(price):
if price < 200:
return "Inexpensive"
elif price < 300:
return "Expensive"
elif price < 400:
return "Very Expensive"
else:
return "Outrageous"
ratings = tiny_monopoly.apply(price_rating, 'Price')
ratings
array(['Expensive', 'Inexpensive', 'Outrageous', 'Inexpensive',
'Expensive', 'Expensive', 'Expensive', 'Expensive', 'Inexpensive',
'Expensive', 'Very Expensive', 'Inexpensive', 'Very Expensive',
'Very Expensive', 'Very Expensive', 'Inexpensive', 'Inexpensive',
'Inexpensive', 'Inexpensive', 'Expensive', 'Inexpensive',
'Inexpensive'], dtype='<U14')
rated_monopoly = tiny_monopoly.with_columns("Cost Rating", ratings)
rated_monopoly
Name | Color | Price | Cost Rating |
---|---|---|---|
Atlantic Avenue | Yellow | 260 | Expensive |
Baltic Avenue | Brown | 60 | Inexpensive |
Boardwalk | Blue | 400 | Outrageous |
Connecticut Avenue | LightBlue | 120 | Inexpensive |
Illinois Avenue | Red | 240 | Expensive |
Indiana Avenue | Red | 220 | Expensive |
Kentucky Avenue | Red | 220 | Expensive |
Marvin Gardens | Yellow | 280 | Expensive |
Mediterranean Avenue | Brown | 60 | Inexpensive |
New York Avenue | Orange | 200 | Expensive |
... (12 rows omitted)
rated_monopoly.where('Cost Rating', 'Inexpensive')
Name | Color | Price | Cost Rating |
---|---|---|---|
Baltic Avenue | Brown | 60 | Inexpensive |
Connecticut Avenue | LightBlue | 120 | Inexpensive |
Mediterranean Avenue | Brown | 60 | Inexpensive |
Oriental Avenue | LightBlue | 100 | Inexpensive |
St. Charles Place | Pink | 140 | Inexpensive |
St. James Place | Orange | 180 | Inexpensive |
States Avenue | Pink | 140 | Inexpensive |
Tennessee Avenue | Orange | 180 | Inexpensive |
Vermont Avenue | LightBlue | 100 | Inexpensive |
Virginia Avenue | Pink | 160 | Inexpensive |
rated_monopoly.where('Cost Rating', 'Outrageous')
Name | Color | Price | Cost Rating |
---|---|---|---|
Boardwalk | Blue | 400 | Outrageous |
Slot Machine#
Suppose we have a slot machine with three wheels, each having four symbols: βπβ, βπβ, βπβ, and βπβ.
slot_symbols = make_array('π', 'π', 'π', 'π')
The payout for our slot machine is described by the following rules:
If there are any lemons, the payout is -1. (That is, you lose your coin.)
If all wheels show cherries, the payout is 15. (You win back your coin plus 15 more.)
In all other cases, the payout is three times the number of bells.
def payout(symbols):
if np.count_nonzero(symbols == 'π') > 0:
return -1
elif np.count_nonzero(symbols == 'π') == len(symbols):
return 15
else:
return 3 * np.count_nonzero(symbols == 'π')
def play_slots():
def slot_machine(wheel1, wheel2, wheel3):
wheels = make_array(wheel1, wheel2, wheel3)
result = payout(wheels)
print()
print("Payout for " + str(wheels) + " is " + str(result))
print()
interact(slot_machine, wheel1 = Choice(slot_symbols), wheel2 = Choice(slot_symbols), wheel3 = Choice(slot_symbols))
play_slots()
check(payout(make_array('π', 'π', 'π')) == -1)
check(payout(make_array('π', 'π', 'π')) == -1)
check(payout(make_array('π', 'π', 'π')) == 15)
check(payout(make_array('π', 'π', 'π')) == 6)
check(payout(make_array('π', 'π', 'π')) == 0)
Letβs look at a table of all possible spins.
from sklearn.utils.extmath import cartesian
spins = Table().with_column('Spin', cartesian([slot_symbols, slot_symbols, slot_symbols]))
spins.show(10)
Spin |
---|
['π' 'π' 'π'] |
['π' 'π' 'π'] |
['π' 'π' 'π'] |
['π' 'π' 'π'] |
['π' 'π' 'π'] |
['π' 'π' 'π'] |
['π' 'π' 'π'] |
['π' 'π' 'π'] |
['π' 'π' 'π'] |
['π' 'π' 'π'] |
... (54 rows omitted)
payouts = spins.with_column('Payout', spins.apply(payout, 'Spin'))
payouts.show(10)
Spin | Payout |
---|---|
['π' 'π' 'π'] | 15 |
['π' 'π' 'π'] | 3 |
['π' 'π' 'π'] | -1 |
['π' 'π' 'π'] | 0 |
['π' 'π' 'π'] | 3 |
['π' 'π' 'π'] | 6 |
['π' 'π' 'π'] | -1 |
['π' 'π' 'π'] | 3 |
['π' 'π' 'π'] | -1 |
['π' 'π' 'π'] | -1 |
... (54 rows omitted)
What proportion of the spins have payouts greater than 0?
positive_payout_proportion = payouts.where('Payout', are.above(0)).num_rows / payouts.num_rows
positive_payout_proportion
0.3125
np.mean(payouts.column('Payout'))
0.921875
Would casinos ever use our slot machines?
Algorithms for Arrays#
Here is an array of numbers:
numbers = np.random.choice(np.arange(0,100,1), 10)
numbers
array([27, 20, 65, 25, 36, 17, 82, 81, 42, 29])
We can add up all the numbers in the array:
sum(numbers)
424
How do we write sum
? We need to be able to do the same thing to every element in the array,
namely add it to a tally weβre keeping. Loops let us do the same thing repeatedly.
for name in ['Katie', 'Steve']:
print(name)
Katie
Steve
for i in np.arange(0,10):
print("iteration", i)
iteration 0
iteration 1
iteration 2
iteration 3
iteration 4
iteration 5
iteration 6
iteration 7
iteration 8
iteration 9
# Steve: Important for prelab to show one loop that accumulates a value...
total = 0
for i in numbers:
total = total + i
total
424
def sum(numbers):
total = 0
for i in numbers:
total = total + i
return total
sum(np.random.choice(np.arange(0,100,1), 100))
4615
def mean(numbers):
return sum(numbers) / len(numbers)
mean(numbers)
42.4
def max(numbers):
"""
requires len(numbers) > 0!
"""
biggest_yet = numbers.item(0)
for i in numbers:
if i > biggest_yet:
biggest_yet = i
return biggest_yet
max(numbers)
82
Simulation and Loops#
Generalization#
Letβs make a reusable version of our simulation. That is, letβs make a function to do the work and produce the outcomes array.
def simulate_coin_tosses():
outcomes = make_array()
number_outcomes = 10000
for i in np.arange(0,number_outcomes):
outcome = sum(np.random.choice(coin, 100) == 'heads')
outcomes = np.append(outcomes, outcome)
return outcomes
Make it general by providing parameters to customize behavior.
def simulate_coin_tosses(number_outcomes):
outcomes = make_array()
for i in np.arange(0,number_outcomes):
outcome = sum(np.random.choice(coin, 100) == 'heads')
outcomes = np.append(outcomes, outcome)
return outcomes
simulate_coin_tosses(5)
array([47., 59., 49., 46., 57.])
What would change if we simulated other kinds of events?
Number of tails in 200 flips?
Sum of 20 dice rolls?
Only thing that changes is the outcome for each individual simulation step:
def simulate(make_outcome, number_outcomes):
outcomes = make_array()
for i in np.arange(0, number_outcomes):
outcome = make_outcome()
outcomes = np.append(outcomes, outcome)
return outcomes
def heads_in_100_flips():
return sum(np.random.choice(coin, 100) == 'heads')
simulate(heads_in_100_flips, 10)
array([54., 45., 51., 46., 44., 43., 52., 50., 54., 51.])
def sum_twenty_dice():
return sum(np.random.choice(np.arange(1,7), 20))
simulate(sum_twenty_dice, 5)
array([69., 62., 70., 69., 60.])