✅ Put your name here

" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Goals for this pre-class assignment\n", "By the end of this assignment, you should be able to:\n", "* Import NumPy into Python and create an manipulate NumPy arrays.\n", "* Use NumPy to do simple calculations with arrays\n", "\n", "### Assignment instructions\n", "\n", "Watch the videos below, do the readings linked to below the videos, and complete the assigned programming problems. Please get started early, and come to office hours if you have any questions! Make use of Teams as well!\n", "\n", "**This assignment is due by 7:59 p.m. the day before class,** and should be uploaded into the appropriate \"Pre-class assignments\" submission folder. Submission instructions can be found at the end of the notebook." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "___\n", "### A brief aside on Jupyter notebooks\n", "Before you get started with this notebook, take a few minutes to make sure you are feeling comfortable with **Jupyter notebooks** at this point in the course. \n", "\n", "* If you still have any questions about how they work, or how to better use them, post your thoughts on our Teams channel. \n", "* It is really important to keep in mind that Jupyter notebooks are based on cells. This is a markdown cell, for example. Because you can execute the cells in any order you wish, *it is up to you to keep track of what has been done, or not*. If it helps, you can make an initial habit of running all cells from the top down, although there will be cases where you won't want to do that. \n", "* It is worth taking a few minutes to get better at keyboard shortcuts, which will make using the notebooks much more efficient; and, learning some markdown is also helpful. Both are in this [webpage](https://murillogroupmsu.com/introduction-to-jupyter-notebooks/), and you can also do a web search to find other tutorials on these topics. \n", "* One of the best things about the notebooks is **rapid prototyping of code**. This means: try something quickly, delete it and move on. With the keyboard shortcuts, this becomes quite fast. Suppose you want to know what \"4 + 5 * 3\" will give. The steps are simple: create a new cell, type that expression in, shift-enter, examine the result, delete that cell, use the result. If you learn the keyboard shortcuts, this prototyping/debugging is fast:\n", " * press \"esc\" to get out of the cell you are in (go into command mode)\n", " * press \"b\" to create a cell below (or \"a\" for above - your choice)\n", " * press \"return\" to enter/activate the cell (to go into edit mode)\n", " * type in your test (e.g., 4 + 5 * 3)\n", " * press \"shift-enter\"\n", " * press \"esc\" to get out of the interior of the cell (go from edit to command mode)\n", " * press \"x\" to delete that temporary cell\n", "* Sometimes, when trying to debug your code, it can be really useful to be able to see the line numbers. To do this:\n", " * press \"esc\" to get out of the cell you are in (to go into command mode)\n", " * press \"l\" (a lowercase \"L\") to turn on lines numbers\n", " \n", "This may seem like a lot of steps, but once you memorize the shortcuts, you can rapidly create, use and delete cells. And using line numbers is a good way to better review your code and discuss it with someone else. When you have an error, this is best way to quickly isolate parts of the code to test them.\n", "\n", "Try it now!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "___\n", "## Getting familiar with NumPy\n", "\n", "Okay, now let's get to the subject of this pre-class assignment: **NumPy**. \n", "\n", "As you learned in the previous course material, Python comes with a large number of extremely useful libraries. In fact, Python itself is a rather small language on its own; it's true power is the myriad of libraries developed for it. In our realm of computational modeling, a core library is [NumPy](https://en.wikipedia.org/wiki/NumPy), which translates to \"Numerical Python\". NumPy allows you to do mathematical operations both more easily (from a coding perspective) and faster (in the sense of how long you need to wait for the result). \n", "\n", "As with other libraries, you include NumPy through an import command. Execute the next cell." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that NumPy gets imported, but also gets renamed as \"np\". You don't need to use \"np\" if you don't want to; but, in the Python community, everyone else does and it makes it easier for people to read each other's code if we all use the same conventions. NumPy is vast. We will be learning aspects of NumPy throughout the entire semester, and this assignment is just the beginning of that journey. \n", "\n", "Why do we have the dot notation in which we will make calls to libraries with `np.`? The reason is that Python is huge and some of the libraries have overlapping functionalities. For example, you may find that NumPy contains libraries that *also* exist in other modules you learn later in the semester. By using the dot notation, you can be sure you are using the library of _your_ choice, and _you_ are free to switch between them throughout your code. Sometimes you will use dots _twice_, as in `np.random.randn(500)`.\n", "\n", "For now, we will focus on the key element of NumPy: the **array**." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Now**, watch the following video to learn about the basics of *NumPy arrays* and how they differ from *lists*, which have been your main tool for storing information up to this point. (If the YouTube version doesn't work, try the [MediaSpace link](https://mediaspace.msu.edu/media/An+Introduction+to+NumPy+ArraysA+NumPy+Array+Basics/1_fz4bh3ng))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.display import YouTubeVideo\n", "YouTubeVideo(\"g7epZeDA_lQ\",width=640,height=360)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "✅ **Question**: Explain, in your own words, some of the similarities and differences between standard Python lists and the NumPy arrays." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "✎ *Put your answer here!*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## Manipulating NumPy arrays and performing mathematical operations\n", "\n", "Now that you understand a bit more about the NumPy array object in Python, watch the following video to understand how we can manipulate NumPy arrays and use them to perform mathematical operations, which is precisely what NumPy arrays were built for! (If the YouTube video doesn't work, try the [MediaSpace link](https://mediaspace.msu.edu/media/An+Introduction+to+NumPy+ArraysA+Operations+and+Arrays/1_qu3lpypx))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.display import YouTubeVideo\n", "YouTubeVideo(\"V2C9expTF1o\",width=640,height=360)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "✅ **Question**: If you had two arrays of the same length and wanted to create a new array that is the product of the first two, how would you do that?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "✎ *Put your answer here*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "✅ **Question**: What functions can I use to find the sum, minimum value, maximum value, and average value of a NumPy array? How do I call these functions? (Provide some example code in your response)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "✎ *Put your answer here*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "___\n", "## 1. Working with NumPy Arrays ##\n", "___\n", "\n", "As you've learned at this point, at the core of NumPy is a data type called an array. An array is like a Python list, but has some very different features. It is best to not confuse them, even if sometimes they might be interchangable. All other opertions in NumPy, and many other Python libraries used for computations, will assume you are using this array type.\n", "\n", "The first thing you need to learn to do is create an array, and there are several ways of doing this depending on your goals. Let's learn two related methods now." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "___\n", "### 1.1 `np.arange`\n", "___\n", "\n", "The `np.arange` function is similar to the `range` function: it creates an array where the entries go from a minimum to a maximum value using an even step size. The arguments are:\n", "\n", "1. The minimum value\n", "2. The maximum value\n", "3. The step size\n", "\n", "so the following command:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "np.arange(0,100,5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "creates an array that goes from `0` to `100` in steps of `5`. **Note that like the `range` command, it does not include the maximum value as an entry in the array.**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "___\n", "### 1.2 `np.linspace`\n", "___\n", "\n", "The `np.linspace` function is similar, in that it creates an array where the entries are *linearly spaced*. But it has one important difference. Its three arguments are:\n", "\n", "1. The minimum value\n", "2. The maximum value\n", "3. *The number of elements*\n", "\n", "so the following command:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "np.linspace(0.1,1,10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "creates an array with 10 elements, linearly (or evenly) spaced, from `0.1` to `1.0`. **Note that, unlike the `range` function, this is inclusive of the endpoints.** In other words, it includes entries for both the minimum and maximum values. **Note also that this is good for dealing with floats!** So, now, say, to create a set of $x$ values spanning $[0,2 \\pi]$, you can use `np.linspace` instead of a `while` loop!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that there is a lot of documentation on the web, such as [this](https://docs.scipy.org/doc/numpy/reference/generated/numpy.linspace.html). **These \"doc pages\" can also be accessed directly in Jupyter using \"?\":**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "np.linspace?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Since these functions are so similar**, it is important not to get them mixed up! Look at the example code below and answer the questions about the differences between `np.arange` and `np.linspace`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# comparing arange to linspace\n", "my_array_range = np.arange(0,10,1) # Make sure you understand how this line is different...\n", "my_array_linspace = np.linspace(0,9,10) # ... than this line\n", "print(\"Using arange I get:\", my_array_range)\n", "print(\"Using linspace I get:\", my_array_linspace)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, in your own words, describe what these functions do. When do you think you would chose to use one over the other? Write your answer in this markdown cell." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "✎ *Put your answer here.*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "___\n", "### 1.3 `np.zeros` and `np.ones`\n", "___\n", "\n", "Believe it or not, a common way to initialize numpy arrays is by filling them with zeros. For this you can use the `np.zeros` function:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "np.zeros(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "which gives us an array of 10 elements, each one equal to zero. Similarly, we could use the `np.ones` function:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "np.ones(10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "to give us an array full of ones." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "___\n", "### 1.4 No mixed data types!\n", "___\n", "\n", "The arrays look a lot like lists. But, a key difference is that you **cannot** have mixed types inside of the array. For example, try this code:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "my_list = [1, 3.1415, 'CMSE'] # this list has three different types in it: integer, float and string\n", "conv_to_array = np.array(my_list) # this converts a list to an array\n", "print(conv_to_array)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What are the types of the elements in the new array? Are they the same as the original list? Are they all the same as each other?\n", "\n", "✅ Try modifying the list with different initial variables types to see if you can figure out the rule Python uses for setting the element type in the array when the conversion step happens." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# code to examine different types of lists to see what np.array does to them\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "___\n", "### 1.5 Mathematical operations\n", "___\n", "\n", "**One of the greatest parts of numpy arrays is that you can change all elements using a single line of code!** This greatly simplifies a lot of the work we've been doing with lists and loops.\n", "\n", "\n", "Let's try some mathematical operations on arrays. \n", "\n", "✅ Make an array that contains the numbers $0$ through $9$. Multiply all the elements by 3, then subtract 7." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Put your code here.`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "✅ Make an array of the first 100 positive integers and **save it as `first_100`**. Compute and print the square of the array as `print(first_100**2)`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Put your code here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "___\n", "### 1.6 Numpy functions\n", "___\n", "\n", "Numpy also contains its own math libraries, highly tuned to be used with NumPy arrays. As always, to access those you need to use the \"dot notation\". For example, run this cell:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# This code cell uses four NumPy methods:\n", "# linspace, pi, sin and cos\n", "x_values = np.linspace(0, 2*np.pi, 200)\n", "sin_times_10sin = np.sin(x_values) * np.sin(10*x_values)\n", "print( sin_times_10sin )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "✅ Describe what you see:\n", "\n", "*I see......*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We recently learned another library: `matplotlib`. Let's combine them. The first thing you need to do is `import` that library:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "✅ Now, plot the `sin_times_10sin` array versus your original `x_values` array. **Don't worry**, matplotlib's `plt.plot` function can accept numpy arrays as arguments! " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# plot of my function\n", "# (be sure to include axis labels!)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "___\n", "### 1.7 Some numpy statistics operations\n", "___\n", "\n", "Finally, let's learn just a few of the easy operations in NumPy for doing statistics. The cell below shows how easy it is to compute the sum, mean, median and standard deviation of a dataset:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ages_dataset = np.array([1,1,2,3,3,5,7,8,9,10,10,11,11,13,13,15,16,17,18,18,\n", "18,19,20,21,21,23,24,24,25,25,25,25,26,26,26,27,27,27,27,27,\n", "29,30,30,31,33,34,34,34,35,36,36,37,37,38,38,39,40,41,41,42,\n", "43,44,45,45,46,47,48,48,49,50,51,52,53,54,55,55,56,57,58,60,\n", "61,63,64,65,66,68,70,71,72,74,75,77,81,83,84,87,89,90,90,91])\n", "\n", "print(\"The sum of the dataset is\",np.sum(ages_dataset))\n", "print(\"The mean of the dataset is\",np.mean(ages_dataset))\n", "print(\"The median of the dataset is\",np.median(ages_dataset))\n", "print(\"The standard deviation of the dataset is\",np.std(ages_dataset))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One useful way to visualize a dataset is with a **histogram**. A histogram is constructed by \"binning\" data. For example, the data above could be binned into a number of age intervals (0-5, 5-10, 10-15, etc.). The x-axis of a histogram are the bins chosen for the data set, and the y-axis is the number of observations that fall into each bin. In Python, we can use the `plt.hist()` function from matplotlib to make one-dimensional histograms:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# a histogram of the ages with the data binned into increments of 10\n", "plt.hist(ages_dataset,bins=10) \n", "plt.xlabel('Age')\n", "plt.ylabel('Frequency')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "✅ Try changing the bin size in the example below and note what happens to the data. \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Put your commented code here:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "\n", "## 2. Reading in Data: Population of Michigan\n", "\n", "We'll be using Numpy to read in data from files in class, so let's get some practice with that now. Along with this pre-class assignment, you should have also downloaded a file called `michigan_pop.csv`. This file is available on the course website right under the link to this notebook. You'll want to right-click and \"Save link as...\".\n", "\n", "**Note**: it is possible that your computer will change the end of the filename to be \"`.txt`\" if this is the case you should make sure to edit the file name to make sure it is \"`.csv`\".\n", "\n", "When we read in data from a file, Python needs to know where that file is. **Therefore, it is crucial that `michigan_pop.csv` is in the same folder as this pre-class notebook.** For example, if this notebook file is in your downloads folder, make sure that `michigan_pop.csv` is also in your downloads folder. You can also choose to \"upload\" the file using your Jupyter notebook interface, if that is normally how you open the notebooks.\n", "\n", "### 2.1 Examining the Data\n", "\n", "* Take a moment to look at the contents of this file (`michigan_pop.csv`) with an editor on your computer. For example, `*.csv` files open with Excel or a simple text editor like NotePad or TextEdit. You can also open it inside the Jupyter interface.\n", "\n", "✅ **Question**: Describe the contents of `michigan_pop.csv`. What does the data look like? (E.g., how many columns of data are there, what do the different columns of data represent, what kind of values/datatypes are in each column, etc.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "✎ *Put your response here*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2.2 Loading the Data\n", "\n", "We are going to use NumPy to read in data from files and look at the data. The standard method for doing this in NumPy is `loadtxt`. In principle, `loadtxt` is simple - it loads your data into NumPy arrays for you to use them. Unfortunately, data seldom comes in an entirely clean form, and you will need to give many options that are file dependent. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "alldata = np.loadtxt(\"michigan_pop.csv\", usecols = (0,1), skiprows = 1, delimiter=',') # example for the michigan population file\n", "\n", "print(alldata)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first argument in `np.loadtxt` (`michigan_pop.csv`) specifies the name of the file we're loading. What do the other arguments specify? What happens if you change them?\n", "\n", "✅ **Task** In the cell below, try out the following:\n", "- Change `usecols` to be equal to `(0)` and print the results. Then change it to `(1)` and print out the results. Describe what changing this variable does to `alldata`.\n", "- Change `skiprows` to be equal to `3` and print the results. Then change it to `5` and print out the results. Describe what changing this variable does to `alldata`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Write code for experimenting here\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- *Describe what changing `usecols` does*\n", "\n", "\n", "\n", "- *Describe what changing `skiprows` does*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The data is currently in the form of a 2D Numpy array, which is less than ideal. We can deal with this by *unpacking* the data into two variables. We unpack the variables using another command line argument, like so." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#Unpacking the data into two separate variables\n", "pop_dates, pop_numbers = np.loadtxt(\"michigan_pop.csv\",\n", " usecols = (0,1),\n", " unpack=True,\n", " skiprows = 1,\n", " delimiter=',') " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Plotting the Data\n", "\n", "✅ **Task** In the cell below, make a plot showing the data you read in from `michigan_pop.csv`. Use the dates for your x values and the total population for your y values." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Write plotting code here\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---\n", "## Assignment wrap-up\n", "\n", "Please fill out the form that appears when you run the code below. **You must completely fill this out in order to receive credit for the assignment!**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.display import HTML\n", "HTML(\n", "\"\"\"\n", "\n", "\"\"\"\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Congratulations, you're done!\n", "\n", "Submit this assignment by uploading it to the course Desire2Learn web page. Go to the \"Pre-class assignments\" folder, find the appropriate submission link, and upload it there.\n", "\n", "See you in class!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "© Copyright 2023, The Department of Computational Mathematics, Science and Engineering at Michigan State University" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.3" } }, "nbformat": 4, "nbformat_minor": 4 }