In [1]:

```
# Set up packages for lecture. Don't worry about understanding this code,
# but make sure to run it if you're following along.
import numpy as np
import babypandas as bpd
import pandas as pd
from matplotlib_inline.backend_inline import set_matplotlib_formats
import matplotlib.pyplot as plt
set_matplotlib_formats("svg")
plt.style.use('ggplot')
np.set_printoptions(threshold=20, precision=2, suppress=True)
pd.set_option("display.max_rows", 7)
pd.set_option("display.max_columns", 8)
pd.set_option("display.precision", 2)
```

- Homework 2 is due
**tomorrow at 11:59PM**. - Lab 3 is due on
**Saturday 4/29 at 11:59PM**. - Come to office hours for help! The schedule is here.
- In addition, we are offering 1-on-1 tutoring to all students in the class. 1-on-1 tutoring is meant for
**conceptual**help, not assignment help. Look here to sign up for Week 4.

- In addition, we are offering 1-on-1 tutoring to all students in the class. 1-on-1 tutoring is meant for
- The Midterm Project will be released
**tomorrow!**- You can work with a partner from any lecture section, but if you do, you must follow these project partner guidelines. In particular, you must both contribute to all parts of the project and not split up the problems.
- We will hold a mixer on
**Wednesday from 1:30 to 2:15PM in the Center Hall courtyard**to help you find a partner if you don't have one. More details to come tomorrow.

**This Thursday from 12-1:30PM in CSE 1202**, a few other DSC professors and I will be participating in a "Hot Ones"-style event hosted by DS3. Come say hi!

- Booleans.
- Conditional statements (i.e.
`if`

-statements). - Iteration (i.e.
`for`

-loops).

**Note:**

- We've finished introducing new DataFrame manipulation techniques.
- Today we'll cover some foundational programming tools, which will be very relevant as we start to cover more ideas in statistics (next week).
**The last lecture that will be in scope for the Midterm Exam is Lecture 12 (this Friday).**

`bool`

is a data type in Python, just like`int`

,`float`

, and`str`

.- It stands for "Boolean", named after George Boole, an early mathematician.

- There are only two possible Boolean values:
`True`

or`False`

.- Yes or no.
- On or off.
- 1 or 0.

- Comparisons result in Boolean values.

In [2]:

```
capstone = 'finished'
units = 123
```

In [3]:

```
units >= 180
```

Out[3]:

False

In [4]:

```
type(units >= 180)
```

Out[4]:

bool

`not`

¶There are three operators that allow us to perform arithmetic with Booleans – `not`

, `and`

, and `or`

.

`not`

flips `True`

↔️ `False`

.

In [5]:

```
capstone
```

Out[5]:

'finished'

In [6]:

```
capstone == 'finished'
```

Out[6]:

True

In [7]:

```
not capstone == 'finished'
```

Out[7]:

False

`and`

operator¶The `and`

operator is placed between two `bool`

s. It is `True`

if **both** are `True`

; otherwise, it's `False`

.

In [8]:

```
capstone
```

Out[8]:

'finished'

In [9]:

```
units
```

Out[9]:

123

In [10]:

```
capstone == 'finished' and units >= 180
```

Out[10]:

False

In [11]:

```
capstone == 'finished' and units >= 120
```

Out[11]:

True

`or`

operator¶The `or`

operator is placed between two `bool`

s. It is `True`

if **at least one** is `True`

; otherwise, it's `False`

.

In [12]:

```
capstone
```

Out[12]:

'finished'

In [13]:

```
units
```

Out[13]:

123

In [14]:

```
capstone == 'finished' or units >= 180
```

Out[14]:

True

In [15]:

```
# Both are True!
capstone == 'finished' or units >= 0
```

Out[15]:

True

In [16]:

```
# Both are False!
capstone == 'not started' or units >= 180
```

Out[16]:

False

In [17]:

```
capstone
```

Out[17]:

'finished'

In [18]:

```
units
```

Out[18]:

123

In [19]:

```
capstone == 'finished' or (capstone == 'in progress' and units >= 180)
```

Out[19]:

True

In [20]:

```
# Different meaning!
(capstone == 'finished' or capstone == 'in progress') and units >= 180
```

Out[20]:

False

In [21]:

```
# "and" has precedence.
capstone == 'finished' or capstone == 'in progress' and units >= 180
```

Out[21]:

True

For instance, `not (a and b)`

is **different** than `not a and not b`

! If you're curious, read more about De Morgan's Laws.

In [22]:

```
capstone
```

Out[22]:

'finished'

In [23]:

```
units
```

Out[23]:

123

In [24]:

```
not (capstone == 'finished' and units >= 180)
```

Out[24]:

True

In [25]:

```
(not capstone == 'finished') and (not units >= 180)
```

Out[25]:

False

`&`

and `|`

vs. `and`

and `or`

¶- Use the
`&`

and`|`

operators between two**Series**. Arithmetic will be done element-wise (separately for each row).- This is relevant when writing DataFrame queries, e.g.
`df[(df.get('capstone') == 'finished') & (df.get('units') >= 180)]`

.

- This is relevant when writing DataFrame queries, e.g.

- Use the
`and`

and`or`

operators between two**individual**Booleans.- e.g.
`capstone == 'finished' and units >= 180`

.

- e.g.

Suppose we define `a = True`

and `b = True`

. What does the following expression evaluate to?

```
not (((not a) and b) or ((not b) or a))
```

A. `True`

B. `False`

C. Could be either one

`in`

operator¶Sometimes, we'll want to check if a particular element is in a list/array, or a particular **substring** is in a string. The `in`

operator can do this for us:

In [26]:

```
3 in [1, 2, 3]
```

Out[26]:

True

In [27]:

```
'ey' in 'hey my name is'
```

Out[27]:

True

In [28]:

```
'dog' in 'hey my name is'
```

Out[28]:

False

`if`

-statements¶- Often, we'll want to run a block of code only if a particular conditional expression is
`True`

. - The syntax for this is as follows (don't forget the colon!):

```
if <condition>:
<body>
```

- Indentation matters!

In [29]:

```
capstone = 'finished'
capstone
```

Out[29]:

'finished'

In [30]:

```
if capstone == 'finished':
print('Looks like you are ready to graduate!')
```

Looks like you are ready to graduate!

`else`

¶If you want to do something else if the specified condition is `False`

, use the `else`

keyword.

In [31]:

```
capstone = 'finished'
capstone
```

Out[31]:

'finished'

In [32]:

```
if capstone == 'finished':
print('Looks like you are ready to graduate!')
else:
print('Before you graduate, you need to finish your capstone project.')
```

Looks like you are ready to graduate!

`elif`

¶- What if we want to check more than one condition? Use
`elif`

. `elif`

: if the specified condition is`False`

, check the next condition.- If that condition is
`False`

, check the next condition, and so on, until we see a`True`

condition.- After seeing a
`True`

condition, it evaluates the indented code and stops.

- After seeing a
- If none of the conditions are
`True`

, the`else`

body is run.

In [33]:

```
capstone = 'in progress'
units = 123
if capstone == 'finished' and units >= 180:
print('Looks like you are ready to graduate!')
elif capstone != 'finished' and units < 180:
print('Before you graduate, you need to finish your capstone project and take',
180 - units, 'more units.')
elif units >= 180:
print('Before you graduate, you need to finish your capstone project.')
else:
print('Before you graduate, you need to take', 180 - units, 'more units.')
```

Before you graduate, you need to finish your capstone project and take 57 more units.

What if we use `if`

instead of `elif`

?

In [34]:

```
if capstone == 'finished' and units >= 180:
print('Looks like you are ready to graduate!')
if capstone != 'finished' and units < 180:
print('Before you graduate, you need to finish your capstone project and take',
180 - units, 'more units.')
if units >= 180:
print('Before you graduate, you need to finish your capstone project.')
else:
print('Before you graduate, you need to take', 180 - units, 'more units.')
```

Below, complete the implementation of the function, `grade_converter`

, which takes in a percentage grade (`grade`

) and returns the corresponding letter grade, according to this table:

Letter | Range |
---|---|

A | [90, 100] |

B | [80, 90) |

C | [70, 80) |

D | [60, 70) |

F | [0, 60) |

Your function should work on these examples:

```
>>> grade_converter(84)
'B'
>>> grade_converter(60)
'D'
```

def grade_converter(grade): if grade >= 90: return 'A' elif grade >= 80: return 'B' elif grade >= 70: return 'C' elif grade >= 60: return 'D' else: return 'F'

In [35]:

```
def grade_converter(grade):
...
```

In [36]:

```
grade_converter(84)
```

In [37]:

```
grade_converter(60)
```

```
def mystery(a, b):
if (a + b > 4) and (b > 0):
return 'bear'
elif (a * b >= 4) or (b < 0):
return 'triton'
else:
return 'bruin'
```

Without running code:

- What does
`mystery(2, 2)`

return? - Find inputs so that calling
`mystery`

will produce`'bruin'`

.

In [38]:

```
def mystery(a, b):
if (a + b > 4) and (b > 0):
return 'bear'
elif (a * b >= 4) or (b < 0):
return 'triton'
else:
return 'bruin'
```

In [ ]:

```
```

In [ ]:

```
```

`for`

-loops¶In [39]:

```
import time
print('Launching in...')
for x in [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]:
print('t-minus', x)
time.sleep(0.5) # Pauses for half a second
print('Blast off! 🚀')
```

`for`

-loops¶- Loops allow us to repeat the execution of code. There are two types of loops in Python; the
`for`

-loop is one of them. - The syntax of a
`for`

-loop is as follows:for <element> in <sequence>: <for body>

- Read this as: "for each element of this sequence, repeat this code."
- Lists, arrays, and strings are all examples of sequences.

- Like with
`if`

-statements, indentation matters!

In [40]:

```
num = 4
print(num, 'squared is', num ** 2)
num = 2
print(num, 'squared is', num ** 2)
num = 1
print(num, 'squared is', num ** 2)
num = 3
print(num, 'squared is', num ** 2)
```

4 squared is 16 2 squared is 4 1 squared is 1 3 squared is 9

In [41]:

```
# The loop variable can be anything!
list_of_numbers = [4, 2, 1, 3]
for num in list_of_numbers:
print(num, 'squared is', num ** 2)
```

4 squared is 16 2 squared is 4 1 squared is 1 3 squared is 9

The line `print(num, 'squared is', num ** 2)`

is run four times:

- On the first iteration,
`num`

is 4. - On the second iteration,
`num`

is 2. - On the third iteration,
`num`

is 1. - On the fourth iteration,
`num`

is 3.

This happens, even though there is no `num =`

anywhere.

Using the array `colleges`

, write a `for`

-loop that prints:

```
Revelle College
John Muir College
Thurgood Marshall College
Earl Warren College
Eleanor Roosevelt College
Sixth College
Seventh College
```

for college in colleges: print(college + ' College')

In [42]:

```
colleges = np.array(['Revelle', 'John Muir', 'Thurgood Marshall',
'Earl Warren', 'Eleanor Roosevelt', 'Sixth', 'Seventh'])
```

In [43]:

```
...
```

Out[43]:

Ellipsis

- Recall, each element of a list/array has a numerical position.
- The position of the first element is 0, the position of the second element is 1, etc.

- We can write a
`for`

-loop that accesses each element in an array by using its position. `np.arange`

will come in handy.

In [44]:

```
actions = np.array(['ate', 'slept', 'exercised'])
feelings = np.array(['content 🙂', 'energized 😃', 'exhausted 😩'])
```

In [45]:

```
len(actions)
```

Out[45]:

3

In [46]:

```
for i in np.arange(len(actions)):
print(i)
```

0 1 2

In [47]:

```
for i in np.arange(len(actions)):
print('I', actions[i], 'and I felt', feelings[i])
```

I ate and I felt content 🙂 I slept and I felt energized 😃 I exercised and I felt exhausted 😩

We don't have to use the loop variable!

In [48]:

```
for i in np.arange(3):
print('🐻')
print('👧🏼')
```

🐻 🐻 🐻 👧🏼

- In the next few lectures, we'll learn how to
**simulate**random events, like flipping a coin.

- Often, we will:
- Run an experiment, e.g. "flip 10 coins."
- Compute some
**statistic**, e.g. "number of heads," and write it down somewhere. - Repeat steps 1 and 2 many, many times using a
`for`

-loop.

`np.append`

¶- This function takes two inputs:
- An array.
- An element to add on to the end of the array.

- It returns a new array. It does not modify the input array.
- We typically use it like this to extend an array by one element:

```
name_of_array = np.append(name_of_array, element_to_add)
```

- ⚠️
**Remember to store the result!**

In [49]:

```
some_array = np.array([])
```

In [50]:

```
np.append(some_array, 'hello')
```

Out[50]:

array(['hello'], dtype='<U32')

In [51]:

```
some_array
```

Out[51]:

array([], dtype=float64)

In [52]:

```
# Need to save the new array!
some_array = np.append(some_array, 'hello')
some_array
```

Out[52]:

array(['hello'], dtype='<U32')

In [53]:

```
some_array = np.append(some_array, 'there')
some_array
```

Out[53]:

array(['hello', 'there'], dtype='<U32')

The function `flip(n)`

flips `n`

fair coins and returns the number of heads it saw. (Don't worry about how it works for now.)

In [54]:

```
def flip(n):
'''Returns the number of heads in n simulated coin flips, using randomness.'''
return np.random.multinomial(n, [0.5, 0.5])[0]
```

In [55]:

```
# Run this cell a few times – you'll see different results!
flip(10)
```

Out[55]:

8

Let's repeat the act of flipping 10 coins, 10000 times.

- Each time, we'll use the
`flip`

function to flip 10 coins and compute the number of heads we saw. - We'll store these numbers in an array,
`heads_array`

. - Every time we use our
`flip`

function to flip 10 coins, we'll add an element to the end of`heads_array`

.

In [56]:

```
# heads_array starts empty – before the simulation, we haven't flipped any coins!
heads_array = np.array([])
for i in np.arange(10000):
# Flip 10 coins and count the number of heads.
num_heads = flip(10)
# Add the number of heads seen to heads_array.
heads_array = np.append(heads_array, num_heads)
```

Now, `heads_array`

contains 10000 numbers, each corresponding to the number of heads in 10 simulated coin flips.

In [57]:

```
heads_array
```

Out[57]:

array([4., 8., 6., ..., 5., 8., 7.])

In [58]:

```
len(heads_array)
```

Out[58]:

10000

In [59]:

```
(bpd.DataFrame().assign(num_heads=heads_array)
.plot(kind='hist', density=True, bins=np.arange(0, 12), ec='w', legend=False,
title = 'Distribution of the number of heads in 10 coin flips')
);
```

- To store our results, we'll typically use an
`int`

or an array. - If using an
`int`

, we define an`int`

variable (usually to`0`

) before the loop, then use`+`

to add to it inside the loop.- Think of this like using a tally.

- If using an array, we create an array (usually empty) before the loop, then use
`np.append`

to add to it inside the loop.- Think of this like writing the results on a piece of paper.

- This pattern – of repeatedly adding to an
`int`

or an array – is called the accumulator pattern.

`for`

-loops in DSC 10¶- Almost every
`for`

-loop in DSC 10 will use the accumulator pattern. Do

**not**use`for`

-loops to perform mathematical operations on every element of an array or Series.- Instead use DataFrame manipulations and built-in array or Series methods.

Helpful video 🎥: For Loops (and when not to use them) in DSC 10.

String are sequences, so we can iterate over them, too!

In [60]:

```
for letter in 'uc san diego':
print(letter.upper())
```

U C S A N D I E G O

In [61]:

```
'california'.count('a')
```

Out[61]:

2

Below, complete the implementation of the function `vowel_count`

, which returns the number of vowels in the input string `s`

(including repeats). Example behavior is shown below.

```
>>> vowel_count('king triton')
3
>>> vowel_count('i go to uc san diego')
8
```

def vowel_count(s): # We need to keep track of the number of vowels seen so far. Before we start, we've seen zero vowels. number = 0 # For each of the 5 vowels: for vowel in 'aeiou': # Count the number of occurrences of this vowel in s. num_vowel = s.count(vowel) # Add this count to the variable number. number = number + num_vowel # Once we've gotten through all 5 vowels, return the answer. return number

In [62]:

```
def vowel_count(s):
# We need to keep track of the number of vowels seen so far. Before we start, we've seen zero vowels.
number = 0
# For each of the 5 vowels:
# Count the number of occurrences of this vowel in s.
# Add this count to the variable number.
# Once we've gotten through all 5 vowels, return the answer.
```

In [63]:

```
vowel_count('king triton')
```

In [64]:

```
vowel_count('i go to uc san diego')
```

`if`

-statements allow us to run pieces of code depending on whether certain conditions are`True`

.`for`

-loops are used to repeat the execution of code for every element of a sequence.- Lists, arrays, and strings are examples of sequences.

- Probability.
- A math lesson – no code!