<jupyter_start><jupyter_text>1. Introduction to Python & Notebooks  This is an interactive jupyter notebook document, accessible at: Page down through it, following the instructions…These computer programming problem set assignments are a required part of the course.  Collaborating on the problem sets is more than okay—it is encouraged! Seek help from a classmate or an instructor or a roommate or a passerby when you get stuck! (Explaining things is beneficial, too—the best way to solidify your knowledge of a subject is to explain it.) But the work has to be your own: no cutting-&-pasting from others' problem sets, please! We want you to learn this stuff, and your fingers typing every keystroke is an important way of building muscle memory here.In fact, we strongly recommend that as you work through this notebook, whenever you come to a "code" cell—something intended not for you to read but also to direct the computer—the python interpreter—to do calculations, you (1) click on the code cell to bring it into your browser's focus; (2) click on the `+` button in the toolbar above to create a new code cell just below the one you were now in; and then (3) retype, line-by-line, the computer code in the cell (not the comment lines beginning with ``s, but the code cells) while trying to figure out what the line of code is intended to tell the python interpreter to do. "Muscle"—in this case, fingertip—memory is an important but undervalued part of "active learning" here at Berkeley. In Germany, however, they have a term for it: _das Fingerspitzengefühl_; it's the kind of understanding-through-the-fingertips that a true expert has.In this problem set, you will learn how to:1. navigate Jupyter notebooks (like this one);2. write and evaluate some basic *expressions* in Python, the computer language of the course;3. call *functions* to use code other people have written; and4. break down python code into smaller parts to understand it.5. Do some initial data explorations with Python in a notebook.With what looks to be a permanent and long-run partial moving-online of the university, the already important topic of “data science” seems likely to become even more foundational.  Hence I am going to try to provide you with an introduction—to “data science”, and to the framework we will be using for problem sets that we hope will make things much easier for you and for us…When you are finished, satisfied, or stuck, print your notebook to pdf, & upload the pdf to the appropriate assignment bCourses page: >Also, please include with your submission all of your comments on and reactions to this assignment that you want us to know... For reference, you might find it useful to read chapter 3 of the Data 8 textbook: >. Chapters 1 > and 2 > are worth skimming as well...----  1.1. Why Are We Doing This?First of all, we are doing this because our section leaders are overworked: teaching online takes more time and effort than teaching in person, and our section leaders were not overpaid before the 'rona arrived on these shores. Taking the bulk of the work of grading calculation assignments off of their backs is a plus—and it appears that the best way for us to do that is to distribute a number of the course assignements to you in this form: the form of a Python computer language "jupyter notebook"Second, we are doing this because learning jupyter notebooks and python may well turn out to be the intellectual equivalent for you of "eat your spinach": something that may seem unpleasant and unappetizing now, but that makes you stronger and more capable. A couple of years ago, I had coffee with a student who had graduated in 2007, and who attributed a large chunk of the interesting and successful career he has had in the past decade-and-a-half years—had in spite of the collapse of the job market in 2008-9—to the fact that he had been fluent in Microsoft Office when he left Berkeley. But now, he said—and I agree—it is not fluency in Word, Powerpoint, and (shudder) Excel that allows one to make oneself useful in a white-collar organization doing interesting work while one learns-by-doing, it is rather fluency in a language like Python and the ability to script hooks into various Big Data and other APIs. An analogy: Back in the medieval European university, people would learn the Trivium—the 'trivial' subjects of Grammar (how to write), Rhetoric (how to speak in public), and lLogic (how to think coherently)—then they would learn the Quadrivium of Arithmetic, Geometry, Music/Harmony, and Astronomy/Astrology; and last they would learn the advanced and professional subjects: Law or Medicine or Theology and Physics, Metaphysics, and Moral Philosophy.But a student would also learn two more things: how to learn by reading—how to take a book and get something useful out of it, without a requiring a direct hands-on face-to-face teacher; and (2) how to write a fine chancery hand so that they could prepare their own documents, for submission to secular courts or to religious bishops or even just put them in a form where they would be easily legible to any educated audience back in those days before screens-and-attachments, before screens-and-printers, before typewriters, before printing.In 1999 Python programming language creator <NAME> compared the ability to read, write, and use software you had built or modified yourself to search and analyze data and information collections. Guido predicted that mass programming, if it could be attained, would produce increases in societal power and changes in societal organization of roughly the same magnitude as mass literacy has had over the past several centuries. Guido may be right, and he may be wrong. But what is clear is that your lives may be richer, and you may have more options, if the data science and basic programming intellectual tools become a useful part of your intellectual panoplies.The Data Science tools may well turn out to be in the first half of the 2000s the equivalent of a _fine chancery hand_, just as a facility with the document formats and commands of the Microsoft office suite were the equivalent of a fine chancery hand at the end of the 1900s: practical, general skills that make you of immense value to most if not nearly all organizations. This—along with the ability to absorb useful knowledge without requiring hands-on person-to-person face-to-face training—will greatly boost your social power and your set of opportunities in your life.If we are right about its value.Why Jupyter and Python, rather than R-studio and R, or C++ and Matlab? Because Jupyter Project founder <NAME> has an office on the fourth floor of Evans. Because 40% of Berkeley undergraduates currently take Data 8 and so, taking account of other channels, more than half of Berkeley students are already going to graduate literonumerate in Python.Is fluency in something like Python in particular and data-science tools in general is becoming, for the 21st Century, the equivalent of what learning to write a fine chancery hand was if you went to Oxford or Cambridge University in the 14th Century? We do not know. We do think we should help you get ready.Third, why Jupyter and Python, rather than R-Studio and R, or C++ and MATLAB, or even (horrors!) Microsoft Ezcel? Because Jupyter Project founder <NAME> has an office on the fourth floor of Evans. Because half of Berkeley undergraduates currently take Data 8 and so, taking account of other channels, more than half of Berkeley students are already going to graduate literate in python.Let us get started!----  1.2. Jupyter NotebooksThis browser window is now showing you a computer science object that is called a "Jupyter notebook". A notebook is a place to write programs and view their results, and also to write text. The text and programs are contained in little boxes called "cells". When the computer thinks that you are paying attention to a particular cell—and may click in it, and then edit it—it surrounds the cell with a blue box, and puts a blue line to the left of the cell.A notebook is an editable document object in which you can write computer programs; view their results; and comment, annotate, and explain what is going on. Project jupyter  is headquartered here at Berkeley, where jupyter originator and ringmaster <NAME>  works: its purpose is to build human-friendly frameworks for interactive computing. If you want to see what Fernando looks and sounds like, you can load and watch a 15-minute inspirational video by clicking on the line 'YouTubeVideo("Wd6a3JIFH0s")' in the cell immediately below this one, and then clicking on the '▶' symbol in the toolbar at the top of the sub-window this cell appears in:<jupyter_code>from IPython.display import YouTubeVideo

# The original URL is: 
# https://www.youtube.com/watch?v=Wd6a3JIFH0s

YouTubeVideo("Wd6a3JIFH0s")<jupyter_output><empty_output><jupyter_text>1.2.1. Code CellsThe _cell_ directly below this one contains one line of code in the Python 3 computer language. You _run_ this line as a program—the computer _executes_ the instructions the cell containss—when you click on the '▶' symbol in the toolbar at the top of this sub-window. (You could also have run the cell by, when the computer has focused on it by your clicking on it, pressing 'shift-return' or 'control-return' on your keyboard.) a code cell will execute all of the code it contains.The line of type in the cell is a _Python expression_.&nbsp;Now try running this cell:<jupyter_code>print("Hello, World!")<jupyter_output>Hello, World!<jupyter_text>and this one:<jupyter_code>print("\N{WAVING HAND SIGN}, \N{EARTH GLOBE ASIA-AUSTRALIA}!")<jupyter_output>👋, 🌏!<jupyter_text>Every 'print' expression commands the computer to print a line of symbols to the screen. Directions as to what is in the line of symbols that it prints are contained between the '(' and the ')' that follow the initial Python command 'print' on the expression line.The first of the two code cells above that you just ran is the standard first computer program to write, either if you are a new student or if you are testing out a new machine or testing out writing in a new programming language. it tells the computer to print out to the screen the symbols 'Hello, World!' What did the second code cell print to the screen, and why?Within a code cell, each 'print' statement's output is printed to the screen on a separate line. The lines are arranged in the order in which the computer, scanning from the top to the bottom of the code cell, encounters the lines.In the code cell immediately below, write and then execute a line of Python that prints out: "Friends don't let friends program in Excel!"<jupyter_code># **answer**<jupyter_output><empty_output><jupyter_text>Remember the <NAME> video? Let's look back on its code cell: This cell tells the computer to enlarge the set of Python commands it understands by finding the `YouTubeVideo` command in the `IPython.display` external library of commands, and then importing that command into its memory. Once it has done that, you can then ask the computer to execute that command—which then constructs a little YouTube video window and plays a YouTube video in it. You ask the computer to do so the in the fourth line of the code cell. Which YouTube video does the computer play? You tell it by writing, after `YouTubVideo` a `(`, then a `"`, then the reference ID of the video, then another `"`, and then, finally, a `'`.Between the first and the last lines of the code cell are two lines that are _comment lines_. Anything on a line that comes after a `` symbol inside a code cell the computer takes to be a comment—something directed at humans, and not at computers, that it should ignore. The comment lines tell you—us—what the URL is for the video that the fourth line is going to command the computer to play.The cell also contains two blank lines. They are just there to give your eyes and brain visual clues to where to look for information, and thus make code cells easier to read.----<jupyter_code>from IPython.display import YouTubeVideo

# The original URL is: 
# https://www.youtube.com/watch?v=Wd6a3JIFH0s

YouTubeVideo("Wd6a3JIFH0s")<jupyter_output><empty_output><jupyter_text>In the code cell immediately below, write and then execute a line of Python that plays your favorite Youtube video inside this notebook:<jupyter_code># **answer**<jupyter_output><empty_output><jupyter_text>1.2.2. Text cellsIn a notebook, each rectangle containing text or code is called a *cell*.Text cells (like this one) can be edited by double-clicking on them. They're written in a simple format created by programmer-flaneur <NAME> called **markdown** > to add formatting and section headings. You almost surely want to learn how to use markdown.After you edit a text cell, click the 'run cell' button at the top that looks like `▶` in the toolbar at the top of this window, or press 'shift-return' on your keyboard to confirm any changes to the text and formatting.  **Question.** This paragraph is in its own text cell.  Try editing it so that this sentence is the last sentence in the paragraph, and then click the 'run cell' `▶` button or 'shift-return'. This sentence, for example, should be deleted. So should this one. **Answer.** This paragraph is in its own text cell.  Try editing it so that this sentence is the last sentence in the paragraph, and then click the 'run cell' `▶` button or 'shift-return'. ----  1.2.3. Writing notebooksYou can use Jupyter notebooks for your own projects or documents.  When you make your own notebook, you'll need to create your own cells for text and code.To add a cell, click the + button in the menu bar.  It will start out as either a markdown text or a code cell.  You can change it to the other type by clicking inside it so it's highlighted, clicking the drop-down box to the left of 'Python 3' in the menu bar, and choosing either 'Code' or 'Markdown'.&nbsp;**Question** Add a code cell below this one.  Write code in it that prints out:       A whole new cell! ♪🌏♪(That musical note symbol is like the Earth symbol.  Its long-form name is `\N{EIGHTH NOTE}`.)Run your cell to verify that it works.<jupyter_code># **answer**<jupyter_output>A whole new cell! ♪ 🌏 ♪<jupyter_text>The expression `"A whole new cell! \N{EIGHTH NOTE} \N{EARTH GLOBE ASIA-AUSTRALIA} \N{EIGHTH NOTE}"` is just a string of symbols. The quotation marks at the start and the end tell Python that it is a string of symbols. Similarly, the expression `"a"`is a (very short) string of symbols. What happens when we tell Python to print it?<jupyter_code>print("a")<jupyter_output>a<jupyter_text>What if we take out the quotation marks?<jupyter_code>print(a)<jupyter_output><empty_output><jupyter_text>----  1.2.4. "Errors"Python is a language, and like natural human languages, it has rules.  It differs from natural language in two important ways:1. The rules are *simple*.  You can learn most of them in a few weeks and gain reasonable proficiency with the language in a semester.2. The rules are *rigid*. If you're proficient in a natural language, you can understand a non-proficient speaker, glossing over small mistakes.  A computer running Python code is not smart enough to do that.Whenever you write code, you'll make mistakes.  When you run a code cell that has errors, Python will sometimes produce error messages to tell you what you did wrong.Errors are okay; even experienced programmers make many errors.  When you make an error, you just have to find the source of the problem, fix it, and move on.When you run code, you have the option to, in the window menubar, click 'Run > Run All Cells', which will run all the code cells in the notebook in order. However, the notebook stops running code cells if it hits an error.We have made an error in the next code cell.  Run it and see what happens. Then correct it:<jupyter_code>print("This line is missing something."<jupyter_output><empty_output><jupyter_text>When you ran the code cell above, you ought to have seen (minus the Data 8 staff's annotations) something like this:The last line of the error output attempts to tell you what went wrong.  The *syntax* of a language is its structure, and this 'SyntaxError' tells you that you have created an illegal structure.  'EOF' means 'end of file', so the message is saying Python expected you to write something more (in this case, a right parenthesis) before finishing the cell.There's a lot of terminology in programming languages, but you don't need to know it all in order to program effectively. If you see a cryptic message like this, you can often get by without deciphering it.  (Of course, if you're frustrated, ask a neighbor or a staff member for help.) Googling the error message is often a very good strategy as well:Try to fix the code above so that you can run the cell and see the intended message instead of an error.<jupyter_code># **answer**<jupyter_output>This line is missing something.<jupyter_text>The first rule of computer programming: MAKING ERRORS IS NOT A PROBLEM. MAKING ERRORS IS AN OPPORTUNITY.----  1.2.5. The KernelThe kernel is a program that executes the code inside your notebook and outputs the results. In the top right of your window, you can see a circle that indicates the status of your kernel. If the circle is empty (⚪), the kernel is idle and ready to execute code. If the circle is filled in (⚫), the kernel is busy running some code. Next to every code cell, you'll see some text that says 'In [...]'. Before you run the cell, you'll see 'In [ ]'. When the cell is running, you'll see 'In [*]'. If you see an asterisk (\*) next to a cell that doesn't go away, it's likely that the code inside the cell is taking too long to run, and it might be a good time to interrupt the kernel (discussed below). When a cell is finished running, you'll see a number inside the brackets, like so: 'In [1]'. The number corresponds to the order in which you run the cells; so, the first cell you run will show a 1 when it's finished running, the second will show a 2, and so on. You may run into problems where your kernel is stuck for an excessive amount of time, your notebook is very slow and unresponsive, or your kernel loses its connection. If this happens, try the following steps:1. At the top of your screen, click **Kernel**, then **Interrupt**.2. If that doesn't help, click **Kernel**, then **Restart**. If you do this, you will have to run your code cells from the start of your notebook up until where you paused your work.3. If that doesn't help, restart your server. First, save your work by clicking **File** at the top left of your screen, then **Save and Checkpoint**. Next, click **Control Panel** at the top right. Choose **Stop My Server** to shut it down, then **Start My Server** to start it back up. Then, navigate back to the notebook you were working on. You'll still have to run your code cells again.----  1.2.6. LibrariesThere are many add-ons and extensions to the core of python that are useful—indeed essential—to using it to get work done. They are contained in what are called libraries. The rest of this notebook needs three libraries. So let us tell the python interpreter to install them. Run the code cell below to do so:<jupyter_code># install the numerical python, python data analysis, and mathematical
# plotting libraries for python

!pip install numpy
!pip install pandas
!pip install matplotlib

import numpy as np
import pandas as pd
import matplotlib as mpl<jupyter_output>Requirement already satisfied: numpy in /Users/braddelong/opt/anaconda3/lib/python3.7/site-packages (1.19.2)
Requirement already satisfied: pandas in /Users/braddelong/opt/anaconda3/lib/python3.7/site-packages (1.1.3)
Requirement already satisfied: python-dateutil>=2.7.3 in /Users/braddelong/opt/anaconda3/lib/python3.7/site-packages (from pandas) (2.8.1)
Requirement already satisfied: pytz>=2017.2 in /Users/braddelong/opt/anaconda3/lib/python3.7/site-packages (from pandas) (2020.4)
Requirement already satisfied: numpy>=1.15.4 in /Users/braddelong/opt/anaconda3/lib/python3.7/site-packages (from pandas) (1.19.2)
Requirement already satisfied: six>=1.5 in /Users/braddelong/opt/anaconda3/lib/python3.7/site-packages (from python-dateutil>=2.7.3->pandas) (1.15.0)
Requirement already satisfied: matplotlib in /Users/braddelong/opt/anaconda3/lib/python3.7/site-packages (3.3.2)
Requirement already satisfied: pillow>=6.2.0 in /Users/braddelong/opt/anaconda3/lib/python3.7/site-packages (from matpl[...]<jupyter_text>----  2. Programming in Python 2.1. Python: Numbers & Variables 2.1.1. VariablesRemember our line that went wrong: `print(a)`? The Python interpreter kernel burped up an error. It said "name is not defined". What does this mean? It means that, without the quotation marks telling Python the a is a string, it thought that the a was the name of something—a variable. But it wasn't. So it did not know what to do.Let's fix that:<jupyter_code>a = "Hello, World!"<jupyter_output><empty_output><jupyter_text>This is an *assignment* statement. It assigns whatever is on the right of the equals sign as the *value* of what the name on the left is. In natural language, we have terminology that lets us quickly reference very complicated concepts.  We don't say, "That's a large mammal with brown fur and sharp teeth!"  Instead, we just say, "Bear!" In Python, we do this with *assignment statements*—something that has a name on the left side of an '=' sign, and an expression that can be evaluated on the right.Now what do you think will happen if we tell Python to`print(a)`?Write a code cell and find out!<jupyter_code># **answer**<jupyter_output>Hello, World!<jupyter_text>----Suppose that we assign something else to a?<jupyter_code>a = 3.25
print(a)

a = 6.02 * 10**23
print(a)

a = 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10
print (a)<jupyter_output>3.25
6.019999999999999e+23
3628800<jupyter_text>**Note**: If, on the last line of a cell, we leave off the `print`:<jupyter_code>a<jupyter_output><empty_output><jupyter_text>When you run a notebook cell, if the last line has a _value_, then Jupyter helpfully prints out that value for you. However, it won't print out prior lines automatically:<jupyter_code>print(2)
3
4<jupyter_output>2<jupyter_text>Above, you should see that 4 is the value of the last expression, 2 is printed because it is within the scope of the print command, but 3 is lost forever because it was neither printed nor last.If we want Python to move to the next line as it prints, we use `\n` to tell it to do so:<jupyter_code>print("stuff: now move to the next line \nmore stuff ")<jupyter_output>stuff: now move to the next linie 
more stuff<jupyter_text>In the code cell below, write and execute a line of Python to print "stuff" on the first line, skip the second line, and then print "more stuff" on the third line:<jupyter_code># **answer**<jupyter_output>stuff 

more stuff<jupyter_text>----  2.1.2. ArithmeticThe line in the next cell subtracts.  Its value is what you'd expect.  Run it:<jupyter_code>3.25 - 1.5<jupyter_output><empty_output><jupyter_text>Many basic arithmetic operations are built into Python.  The textbook section on [Expressions](http://www.inferentialthinking.com/chapters/03/1/expressions.html) describes all the arithmetic operators used in the course.  The common operator that differs from typical math notation is '\*\*', which raises one number to the power of the other. **NOT '^'.** Thus '2**3' stands for $2^3$ and evaluates to 8. The order of operations and parentheses is the same as what you learned in elementary school. For example, compare:<jupyter_code>3+6*5-6*3**2*2**3/4*7<jupyter_output><empty_output><jupyter_text>to:<jupyter_code>4+(6*5-(6*3))**2*((2**3)/4*7)<jupyter_output><empty_output><jupyter_text>In standard math notation, the first expression is>$3 + 6 \times 5 - 6 \times 3^2 \times \frac{2^3}{4} \times 7$,while the second expression is>$3 + (6 \times 5 - (6 \times 3))^2 \times (\frac{(2^3)}{4} \times 7)$. There are some things to beware of in Python with respect to the standard arithmetic symbols:<jupyter_code>print("2+2 =", 2+2)
print("'2'+'2' =", "2"+"2")<jupyter_output>2+2 = 4
'2'+'2' = 22<jupyter_text>If the designers of Python had been ruthlessly pedantic, they might have made us write    define the name ten to hereafter have the value of 3 * 2 + 4 instead.  You will probably appreciate the brevity of `=`! But keep in mind that this is the real meaning. `=` does not assert or declare that what is on the left is equal to whqt is on the right. Rather, it takes what is on the right and stuffs it into the metaphorical box which has the name on the left.Suppose that you do want to use the equals sign in the normal way? You have to use `==`. Here is an example:<jupyter_code>a = 4

if (a == 4): 
  print("everything is ok")
else:
  print("something is wrong!")
a = 3

if (a == 4): 
  print("everything is ok")
else:
  print("something is wrong!")
a = 4

if (a = 4): 
  print("everything is ok")
else:
  print("something is wrong!")<jupyter_output><empty_output><jupyter_text>See? That last made the Python interpeter barf. By contrast, in the first of the three code cells, Python checked to make sure that variable a was in fact equal to four, and then reassured us. In the second of the thress code cells, Python checked, found out that a was not in fact equal to three, and called for help. But it just could not handle the third.---- A common pattern in Jupyter notebooks is to assign a value to a name and then immediately evaluate the name in the last line in the cell so that the value is displayed as output.<jupyter_code>close_to_pi = 355/113
close_to_pi<jupyter_output><empty_output><jupyter_text>Another common pattern is that a series of lines in a single cell will build up a complex computation in stages, naming the intermediate results.<jupyter_code>semimonthly_salary = 841.25
monthly_salary = 2 * semimonthly_salary
number_of_months_in_a_year = 12
yearly_salary = number_of_months_in_a_year * monthly_salary
yearly_salary<jupyter_output><empty_output><jupyter_text>Names in Python can have letters (upper- and lower-case letters are both okay, and count as different letters), underscores, and numbers.  The first character can't be a number (otherwise a name might look like a number).  And names can't contain spaces, since spaces are used to separate pieces of code from each other.Other than those rules, what you name something doesn't matter *to Python*.  For example, this cell does the same thing as the above cell, except everything has a different name:<jupyter_code>a = 841.25
b = 2 * a
c = 12
d = c * b
d<jupyter_output><empty_output><jupyter_text>**However**, *names are very important for making your code readable* to yourself and others.  The cell above is shorter, but it's totally useless without an explanation of what it does. When you write any computer code, you must do so assuming that it will need to be read and used by the biggest idiot in the known world. Why? Because when you come back to your own code and need to use it, whether next year, next month, next week, tomorrow, or after dinner, you will soon discover that you are that idiot.----  2.1.3. ListsLists are ordered collections of objects that have an order. Lists allow us to store groups of variables under one name. The order then allows us to access the objects in the list for easy access and analysis. If you want an in-depth look at the capabilities of lists, take a look at >To initialize a list, you use brackets. Putting objects separated by commas in between the brackets will add them to the list. For example, we can create and name an empty list:<jupyter_code>list_example = []
print(list_example)<jupyter_output>[]<jupyter_text>We can add an object to the end of a list:<jupyter_code>list_example = list_example + [5]
print(list_example)<jupyter_output>[5]<jupyter_text>Now we have a one-element list. And we can add another element:<jupyter_code>list_example = list_example + [10]
print(list_example)<jupyter_output>[5, 10]<jupyter_text>to make a two-element list. In the code cell below, make and then print to screen a five-element list called "five_element_list", in which the elements are: 5, 4, 3, 2, "colorless green ideas":<jupyter_code># **answer**<jupyter_output><empty_output><jupyter_text>We can join—"concatenate"—two lists together:<jupyter_code>list_example_two = list_example + [1, 3, 6, 'lists', 'are', 'fun', 4]
print(list_example_two)<jupyter_output>[5, 10, 1, 3, 6, 'lists', 'are', 'fun', 4]<jupyter_text>>**Digression**: It is, I think, a mistake for python to use '+' in this way. In arithmetic, '+' is simply addition. With lists, '+' smashes the two lists on either side together to make a bigger list. this 'overloading' of '+' can be a source of great confusion. For example:<jupyter_code># overloading of the `+` operator considered harmful:

four = 4
print(" This '4' is a number:", four, "; so '+' is addition \n and so", four, "+", four, "=", 
      four + four)

four = [4]
print("\n This '4' is a list:", four, "; so '+' is list concatenation \n and so", four, "+", four, "=", 
      four + four)

four = '4'
print("\n Even worse is: this '4' is a string-of-symbols: \n", four, "; so '+' is symbol concatenation \n and so", four, "+", four, "=", 
      four + four)<jupyter_output>This '4' is a number: 4 ; so '+' is addition 
 and so 4 + 4 = 8

 This '4' is a list: [4] ; so '+' is list concatenation 
 and so [4] + [4] = [4, 4]

 Even worse is: this '4' is a string-of-symbols: 
 4 ; so '+' is symbol concatenation 
 and so 4 + 4 = 44<jupyter_text>To access not the list as a whole but an individual value in the list, simply count from the start of the list, and put the place of the object you want to access in brackets after the name of the list. **But you have to start counting from not one but zero.** Thus the initial object of a list has index 0, the second object of a list has index 1, and in the list above the eighth object has index 7:<jupyter_code>selected_example = list_example_two[7]
print(selected_example)<jupyter_output>fun<jupyter_text>which is indeed the eighth item of 'list_example_two'.(This can become an enormous pain! I find it useful to keep my head straight to talk about "list item 7" and "the 8th item on the list"—which are, in fact, the same.)You may have noticed already that lists do not have to be made up of elements of the same kind. Indices do not have to be taken one at a time, either. Instead, we can take a 'slice;\' of indices, and return the elements at those indices as a separate list. Suppose we just want to select out items 4 through 6 from a list. We can do so:<jupyter_code>selected_list = list_example_two[4:7]
print(selected_list)<jupyter_output>[6, 'lists', 'are']<jupyter_text>We can select out the largest and smallest items of a list via `min` and `max`:<jupyter_code># A list containing six integers.
a_list = [1, 6, 4, 8, 13, 2]

# Another list containing six integers.
b_list = [4, 5, 2, 14, 9, 11]

print('Max of a_list:', max(a_list))
print('Min of b_list:', min(a_list))<jupyter_output>Max of a_list: 13
Min of b_list: 1<jupyter_text>----A list is flexible: its elements can be anything. But often we want our lists to be things that we can do arithmetic on quickly and simply. to help us do this, we have the numerical python library: `numpy` or `np`, and the type pf lists we call _arrays_. Let us start by making an array that consists of the numbers from zero to nine:<jupyter_code>import numpy as np

example_array = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
print("Example Array:", example_array)<jupyter_output>Example Array: [0 1 2 3 4 5 6 7 8 9]<jupyter_text>This could have been accomplished more quickly:<jupyter_code>example_array_2 = np.arange(10)
print('Another Example Array: ', example_array_2)<jupyter_output>Another Example Array:  [0 1 2 3 4 5 6 7 8 9]<jupyter_text>Multiplying a list and an array by a number produce different results:<jupyter_code>b_list = [4, 5, 2, 14, 9, 11]
print('Multiplying a list by 2: ', 2 * b_list)

b_array = np.array([4, 5, 2, 14, 9, 11])
print('Multiplying an array by 2: ', 2 * b_array)<jupyter_output>Multiplying a list by 2:  [4, 5, 2, 14, 9, 11, 4, 5, 2, 14, 9, 11]
Multiplying an array by 2:  [ 8 10  4 28 18 22]<jupyter_text>----  2.2. LoopingLoops > are  useful in manipulating, iterating over, or transforming large lists and arrays. The __for loop__ is useful in that it travels through a list, performing an action at each element. The following code cell moves through every element in example_array, adds it to the previous element in example_array, and copies this sum to a new array.<jupyter_code># loop for calculating the labor force in the
# model over the next 100 years

Labor_Force = []
L = 10
n = .01
T = 100

for i in range(T + 1):
    Labor_Force = Labor_Force + [L]
    L = L * (1 + n)

print(Labor_Force)<jupyter_output>[1, 1.01, 1.0201, 1.030301, 1.04060401, 1.0510100501, 1.061520150601, 1.0721353521070098, 1.08285670562808, 1.0936852726843609, 1.1046221254112045]<jupyter_text>The most important line in the above cell is the 'for i in...' line. This statement sets the structure of our  loop, instructing the machine to stop at every number in `range(T+1)`, perform the indicated operations, and then move on. Once Python has stopped at every element in `range(T+1)`, the loop is completed and the final line, which outputs `Labor_Force`, is executed.In the code cell below, write a loop to calculate the labor force over the next hundred years if (a) its initial value is 50, and (b) if its growth rate is 2% per year:<jupyter_code># **answer**<jupyter_output>[50, 51.0, 52.02, 53.0604, 54.121608, 55.204040160000005, 56.308120963200004, 57.434283382464, 58.582969050113284, 59.75462843111555, 60.94972099973786, 62.16871541973262, 63.41208972812728, 64.68033152268983, 65.97393815314362, 67.2934169162065, 68.63928525453063, 70.01207095962125, 71.41231237881368, 72.84055862638995, 74.29736979891776, 75.78331719489611, 77.29898353879403, 78.84496320956991, 80.42186247376131, 82.03029972323654, 83.67090571770127, 85.3443238320553, 87.0512103086964, 88.79223451487033, 90.56807920516773, 92.37944078927109, 94.22702960505652, 96.11157019715765, 98.0338016011008, 99.99447763312283, 101.99436718578528, 104.03425452950098, 106.11493962009101, 108.23723841249283, 110.40198318074269, 112.61002284435754, 114.8622233012447, 117.15946776726959, 119.50265712261498, 121.89271026506728, 124.33056447036863, 126.817175759776, 129.35351927497152, 131.94058966047095, 134.57940145368036, 137.27098948275398, 140.01640927240905, 142.81673745785724, 145.6730722070144, [...]<jupyter_text>We have done our calculation. But the form in which the computer presents it to us is nearly unreadable.So now let us do a little magic, using the `pandas` or `pd` library::<jupyter_code># calculating the labor force for the next 100 years

import numpy as np
import pandas as pd

Labor_Force = []
L = 100
n = .01

for i in range(101):
    Labor_Force = Labor_Force + [L]
    L = L * (1 + n)

pd.DataFrame(Labor_Force).plot(title = "Labor Force", xlabel = "Year", 
    ylabel = "Value")<jupyter_output><empty_output><jupyter_text>Once we have told Python that we want it to think of the list `Labor Force` as a **pandas DataFrame**, simply adding `.plot()` at the end of our expression will create a graph. And we can put the labels and such for the graph inside the final `()`. We are not limited to simply plotting one series:<jupyter_code># calculating the labor force and the efficiency-of-labor for the next 100 years

Year = []

Labor_Force = []
L = 10
n = 0.01

Efficiency_of_Labor = []
E = 10
g = 0.02

for i in range(101):
    Labor_Force = Labor_Force + [L]
    L = L * (1 + n)
    Efficiency_of_Labor = Efficiency_of_Labor + [E]
    E = E * (1 + g)
    Year = Year + [i]

pd.DataFrame([Year, Labor_Force, Efficiency_of_Labor]
    ).transpose().plot()<jupyter_output><empty_output><jupyter_text>And, once again, we can place legends and clean-up the graph by putting things inside the final parentheses:<jupyter_code>pd.DataFrame([Year, Labor_Force, Efficiency_of_Labor]
    ).transpose().plot(
    title = "Growth Model Variables", xlabel = "Year", 
    ylabel = "Value", legend = 0)<jupyter_output><empty_output><jupyter_text>----  2.3. ReflectionDo not let any of this scare you. It is about building tools so that you can think better. And, at the bottom, all we are doing is counting things—but doing so by standing on the shoulders of giants, who have figured out how to enable us to count things in incredibly compressed, incredibly powerful ways.Listen to physicist <NAME> explain how his QED model of light-matter interactions is simply counting things—adding up all the possible different ways a photon might interact with an electron—by analogy:>“An analogy.... The Maya Indians were interested in... [the War-Star] Venus.... To make calculations, the Maya had invented a system of bars and dots to represent numbers... and had rules by which to calculate and predict not only the risings and settings of Venus, but other celestial phenomena.... Only a few Maya priests could do such elaborate calculations.... Suppose we were to ask one of them how to do just one step in the process of predicting when Venus will next rise as a morning star—subtracting two numbers..... How would the priest explain?.... >He could either teach us the... bars and dots and the rule... or he could tell us what he was really doing: ‘Suppose we want to subtract 236 from 584. First, count out 584 beans and put them in a pot. Then take out 236 beans and put them to one side. Finally, count the beans left in the pot. That number is the result....’ You might say, ‘My Quetzalcoatl! What tedium... what a job!’ To which the priest would reply, ‘That’s why we have the rules.... The rules are tricky, but they are a much more efficient way of getting the answer.... We can predict the appearance of Venus by counting beans (which is slow, but easy to understand) or by using the tricky rules (which is much faster, but you must spend years in school to learn them)’...Python is the equivalent of learning a bunch of such rules, and practicing applying them. ----  3. Growth Models   3.1. Behavioral Relationships Let us set out the basic Solow Growth Model:We assume that a particular economy’s labor force L's proportional rate $ g_L $ is a constant _for that particular economy_ n: > $ \frac{dL}{dt} = g_LL = nL $We also assume that a particular economy’s efficiency-of-labor E's proportional growth rate g is a constant _for that particular economy_ g:>$ \frac{dE}{dt} = gE $We assume the production function for output-per-worker y: > $ y = \kappa^\theta E $Total output is equal to the labor force times output per worker:> $ Y = yL $The capital stock is equal to capital-intensity times total output:> $ K = \kappa Y $Each year a fraction s of total gross output is invested and added to the capital stock, and a fraction $ \delta $ of the capital stock depreciates:> $ \frac{dK}{dt} = sY - \delta KThe code cell below sets up this model, and prints out a graph of the calculated values for the variables:<jupyter_code># basic solow growth model code cell:

# ----
# PARAMETERS AND INITIAL CONDITIONS BLOCK

T = 500                           # number of years for model run

L_0 = 4                           # initial labor force
n = 0.02                          # labor-force growth rate
E_0 = 1                           # initial labor effiency
g = 0.00                          # labor efficiency growth rate
kappa_0 = 2                       # initial capital-intensity
theta = 1                         # salience of capital in the production function
alpha = theta/(1 + theta)         # convenient transformation of theta
Y_0 = kappa_0**theta * E_0 * L_0  # initial total output
y_0 = kappa_0**theta * E_0        # initial productivity
K_0 = kappa_0 * Y_0               # initial capital stock
s = 0.2                           # savings share of gross output
delta = 0.03                      # capital depreciation rate

# END BLOCK
# ----

import numpy as np                # import libraries
import pandas as pd
import matplotlib.pyplot as plt

L_series = [L_0]                  # initialize time-series lists
E_series = [E_0]
Y_series = [Y_0]
y_series = [y_0]
K_series = [K_0]
kappa_series = [kappa_0]

L = L_0                           # initialize working variables
E = E_0
Y = Y_0
y = y_0
K = K_0
kappa = kappa_0

for i in range(T):                # loop for calculating next-year values
    L = (1 + n) * L
    E = (1 + g) * E
    K = (1 - delta) * K + s * Y 
    Y = K**alpha * (E * L)**(1 - alpha)
    y = K**alpha * E
    kappa = K/Y
    L_series = L_series + [L]     # update time series
    E_series = E_series + [E]
    K_series = K_series + [K]
    Y_series = Y_series + [Y]
    y_series = y_series + [y]
    kappa_series = kappa_series + [kappa]

solow_df = pd.DataFrame()         # create dataframe
solow_df['Labor Force'] = L_series
solow_df['Efficiency of Labor'] = E_series
solow_df['Capital Stock'] = K_series
solow_df['Total Output'] = Y_series
solow_df['Capital-Intensity'] = kappa_series
solow_df['Output per Worker'] = y_series

ax = solow_df.plot()              # plot variables
ax.set_title("Model Run")
ax.set_xlabel("Date")
ax.set_ylabel("Value")

plt.show()                        # show plot<jupyter_output><empty_output><jupyter_text>Suppose we just wanted to graph the labor force. Then—after running the code cell above—we would write this, and get the Python Interpreter to execute it:<jupyter_code>ax = solow_df['Labor Force'].plot() # plot the labor force
ax.set_title("Labor Force")
ax.set_xlabel("Date")
ax.set_ylabel("Value")

plt.show()                          # show plot<jupyter_output><empty_output><jupyter_text>Now you write a code cell, plotting just capital-intensity:<jupyter_code># **answer**<jupyter_output><empty_output><jupyter_text>Now you write a code cell, plotting just output per worker:<jupyter_code># **answer**<jupyter_output><empty_output><jupyter_text>Suppose we started the economy in a different initial condition—with an initial capital-intensity of not 2 but 12. How much difference do we think it would make in the long run?Below is a copy of the Basic Solow Growth Model code cell. In it, in the `kappa_0 = 2` line, edit the line to change the 2 to 8, and then rerun the cell:<jupyter_code># **answer**

# basic solow growth model code cell cell:

# ----
# PARAMETERS AND INITIAL CONDITIONS BLOCK

T = 500                           # number of years for model run

L_0 = 4                           # initial labor force
n = 0.02                          # labor-force growth rate
E_0 = 1                           # initial labor effiency
g = 0.00                          # labor efficiency growth rate
kappa_0 = 12                      # initial capital-intensity
theta = 1                         # salience of capital in the production function
alpha = theta/(1 + theta)         # convenient transformation of theta
Y_0 = kappa_0**theta * E_0 * L_0  # initial total output
y_0 = kappa_0**theta * E_0        # initial productivity
K_0 = kappa_0 * Y_0               # initial capital stock
s = 0.2                           # savings share of gross output
delta = 0.03                      # capital depreciation rate

# END BLOCK
# ----

import numpy as np                # import libraries
import pandas as pd
import matplotlib.pyplot as plt

L_series = [L_0]                  # initialize time-series lists
E_series = [E_0]
Y_series = [Y_0]
y_series = [y_0]
K_series = [K_0]
kappa_series = [kappa_0]

L = L_0                           # initialize working variables
E = E_0
Y = Y_0
y = y_0
K = K_0
kappa = kappa_0

for i in range(T):                # loop for calculating next-year values
    L = (1 + n) * L
    E = (1 + g) * E
    K = (1 - delta) * K + s * Y 
    Y = K**alpha * (E * L)**(1 - alpha)
    y = K**alpha * E
    kappa = K/Y
    L_series = L_series + [L]     # update time series
    E_series = E_series + [E]
    K_series = K_series + [K]
    Y_series = Y_series + [Y]
    y_series = y_series + [y]
    kappa_series = kappa_series + [kappa]

solow_df = pd.DataFrame()         # create dataframe
solow_df['Labor Force'] = L_series
solow_df['Efficiency of Labor'] = E_series
solow_df['Capital Stock'] = K_series
solow_df['Total Output'] = Y_series
solow_df['Capital-Intensity'] = kappa_series
solow_df['Output per Worker'] = y_series

ax = solow_df.plot()              # plot variables
ax.set_title("Model Run")
ax.set_xlabel("Date")
ax.set_ylabel("Value")

plt.show()                        # show plot<jupyter_output><empty_output><jupyter_text>Now plot capital-intensity for the new model run:<jupyter_code># **answer**<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07608138524279634, 'fraction_numerical': 0.03581218104428052, 'mean_word_length': 4.133150308853809, 'pattern_counts': {'":': 2, '<': 183, '<?xml version=': 0, '>': 209, 'https://': 2, 'lorem ipsum': 0, 'www.': 3, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 15, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '50', 'dir': 'jupyter-structured-clean-dedup', 'id': '492517', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 14064, 'n_tokens_neox': 12714, 'n_words': 6459, 'path': 'econ-135-s2022-ps01.ipynb', 'repo_name': 'braddelong/2022-jupyter', 'size': '44928'}