In [1]:

```
# Run this cell to set up packages for lecture.
from lec10_imports import *
```

- Homework 2 is due
**tomorrow at 11:59PM**. - Lab 3 is due
**Thursday at 11:59PM**.

- In the project, you'll explore a dataset of top songs on Spotify from 2021-2022, and answer questions such as:
"What musical qualities distinguish the biggest hits from the rest?"

Here's a sneak peek:

**Start early!**Projects are substantially more involved than homeworks.

- 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 in the second half of the class.

`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]:

```
dept = 'DSC'
course = 10
```

In [3]:

```
course < 20
```

Out[3]:

True

In [4]:

```
type(course < 20)
```

Out[4]:

bool

`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, and it also results in a Boolean value.

In [5]:

```
course in [10, 20, 30]
```

Out[5]:

True

In [6]:

```
'DS' in dept
```

Out[6]:

True

In [7]:

```
'DS' in 'Data Science'
```

Out[7]:

False

`not`

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

, `and`

, and `or`

.

`not`

flips `True`

↔️ `False`

.

In [8]:

```
dept == 'DSC'
```

Out[8]:

True

In [9]:

```
not dept == 'DSC'
```

Out[9]:

False

`and`

operator¶The `and`

operator is placed between two `bool`

s. It is `True`

if **both** are `True`

; otherwise, it's `False`

.

In [10]:

```
80 < 30 and course < 20
```

Out[10]:

False

In [11]:

```
80 > 30 and course < 20
```

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]:

```
course in [10, 20, 30, 80] or type(course) == str
```

Out[12]:

True

In [13]:

```
# Both are True!
course in [10, 20, 30, 80] or type(course) == int
```

Out[13]:

True

In [14]:

```
# Both are False!
course == 80 or type(course) == str
```

Out[14]:

False

In [15]:

```
course == 10 or (dept == 'DSC' and dept == 'CSE')
```

Out[15]:

True

In [16]:

```
# Different meaning!
(course == 10 or dept == 'DSC') and dept == 'CSE'
```

Out[16]:

False

In [17]:

```
# With no parentheses, "and" has precedence.
course == 10 or dept == 'DSC' and dept == 'CSE'
```

Out[17]:

True

`&`

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.
`courses[(courses.get('dept') == 'DSC') & (courses.get('course') == 10)]`

.

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

- Use the
`and`

and`or`

operators between two**individual**Booleans.- e.g.
`dept == 'DSC' and course == 10`

.

- e.g.

`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 [18]:

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

Out[18]:

'finished'

In [19]:

```
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 [20]:

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

Out[20]:

'finished'

In [21]:

```
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 [22]:

```
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 [23]:

```
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 [24]:

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

In [25]:

```
grade_converter(84)
```

In [26]:

```
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 [27]:

```
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 [28]:

```
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 [29]:

```
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 [30]:

```
# 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
Eighth College
```

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

In [31]:

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

In [32]:

```
...
```

Out[32]:

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 [33]:

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

In [34]:

```
len(actions)
```

Out[34]:

3

In [35]:

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

0 1 2

In [36]:

```
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 ran and I felt exhausted 😓

We don't have to use the loop variable!

In [37]:

```
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 [38]:

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

In [39]:

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

Out[39]:

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

In [40]:

```
some_array
```

Out[40]:

array([], dtype=float64)

In [41]:

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

Out[41]:

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

In [42]:

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

Out[42]:

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 [43]:

```
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 [44]:

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

Out[44]:

6

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 [45]:

```
# 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)
```

`heads_array`

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

In [46]:

```
heads_array
```

Out[46]:

array([5., 7., 6., ..., 2., 5., 6.])

In [47]:

```
len(heads_array)
```

Out[47]:

10000

In [48]:

```
(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 [49]:

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

U C S A N D I E G O

In [50]:

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

Out[50]:

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 [51]:

```
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 [52]:

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

In [53]:

```
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!