{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Module 7: NumPy Arrays\n", "## Chapter 7 from the Alex DeCaria textbook: 'NumPy Arrays'\n", "\n", "The Numpy module, which is readily installed with my Python distributions, is designed to work with large data sets, particularly those with multiple dimensions. However, unlike Python lists and tuples, NumPy arrays cannot hold multiple data types. For example, a defined numpy array must be all floating numbers, strings, integers, ect.... Despite this rule, it is much more computationally efficient to work with NumPy arrays than with lists/tuples. For this lecture, we will learn how to: \n", "- Create arrays\n", "- Review common NumPy data types\n", "- Go over useful array functions\n", "- Discuss array indexing and subsetting\n", "- Learn how to reshape arrays\n", "- Combine logical operators with arrays\n", "\n", "**Note:** There are *ALOT* of things you can do with NumPy arrays, so for the purpose of time, we will not be abe to go over every function/trick related to NumPy arrays. *It will be up to you* to read the DeCaria book and review other online resources! This lecture is meant to give you the tools so that you can work with basic NumPy arrays.\n", "\n", "**Before starting:** Make sure that you open up a Jupyter notebook session using OnDemand so you can interactively follow along with today's lecture! Also, be sure to copy this script into your atmos5340/module_7 subdirectory!\n", "\n", "

\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Creating an array\n", "\n", "**Opening files:** There are many ways one can create an array using NumPy. The most simple way to this is supply NumPy's array function and give it a list/tuple as its input. Before starting, you must load the NumPy module:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "then, we can create a 1D array by doing the following:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "a = np.array([1,5,3,-6,-2,4,-9,2,2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The array that we created will be all integers, since we only supplied it with integer values. " ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "numpy.ndarray" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(a)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "numpy.int64" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(a[0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "However, we can also create an array and predefine the data type using the `dtype` agrument:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "a = np.array([1,5,3,-6,-2,4,-9,2,2],dtype=np.float64)\n", "print(type(a[0]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here, you can see that the first element in array a is now a floating number." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "Listed below are the data typs most commonly used within NumPy arrays:\n", "\n", ">- `np.float`: Double percision (64 bit) floating point\n", ">- `np.int64`: Double percision (64 bit) integer\n", ">- `np.complex128`: Complex number, with a real and imaginary part that are each 64 bits\n", ">- `np.bool_`: Boolean (True/False) data type. Note the underscore `_`. \n", "\n", "
\n", "\n", "You can also create 2-D arrays (or other multidimensional arrays) by inserting nested lists/tuples as the input for `np.array` function...\n" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 2 5]\n", " [ 1 -4]]\n" ] } ], "source": [ "a = np.array([[2,5],[1,-4]])\n", "print(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, you can also create arrays using single values:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]\n", " [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]\n" ] } ], "source": [ "a_zero = np.zeros((10,10))\n", "print(a_zero)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "or" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[nan nan nan nan nan nan nan nan nan nan]\n", " [nan nan nan nan nan nan nan nan nan nan]\n", " [nan nan nan nan nan nan nan nan nan nan]\n", " [nan nan nan nan nan nan nan nan nan nan]\n", " [nan nan nan nan nan nan nan nan nan nan]\n", " [nan nan nan nan nan nan nan nan nan nan]\n", " [nan nan nan nan nan nan nan nan nan nan]\n", " [nan nan nan nan nan nan nan nan nan nan]\n", " [nan nan nan nan nan nan nan nan nan nan]\n", " [nan nan nan nan nan nan nan nan nan nan]]\n" ] } ], "source": [ "a_nan = np.empty((10,10))\n", "a_nan[:] = np.nan \n", "print(a_nan)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Personally, I like using NaN arrays when I want to fill in the data later on..." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "# Sequential arrays\n", "\n", "There are 3 functions that are primarily used to generate sequential arrays in Python. These functions are `arange()`, `linspace()`, and `logspace()`. The `arange()` function behaves very similarly to the `range()` function in Python:\n" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0 2 4 6 8 10]\n" ] } ], "source": [ "seq_array = np.arange(0,11,2)\n", "print(seq_array)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[11 9 7 5 3 1]\n" ] } ], "source": [ "seq_array = np.arange(11,0,-2)\n", "print(seq_array)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And you get the idea... The data type of the array is determined by the input. So if all the inputs are integers, it will be an integer-type data array. Note that you can define the dtype argument when using the `np.arange` function.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "The `linspace()` function allows the user to specify a begining and end value and the number of points to create:\n" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 1. 1.31034483 1.62068966 1.93103448 2.24137931 2.55172414\n", " 2.86206897 3.17241379 3.48275862 3.79310345 4.10344828 4.4137931\n", " 4.72413793 5.03448276 5.34482759 5.65517241 5.96551724 6.27586207\n", " 6.5862069 6.89655172 7.20689655 7.51724138 7.82758621 8.13793103\n", " 8.44827586 8.75862069 9.06896552 9.37931034 9.68965517 10. ]\n" ] }, { "data": { "text/plain": [ "30" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "seq_array = np.linspace(1,10,30)\n", "print(seq_array)\n", "len(seq_array)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "Finally, the `np.logspace()` function works similar to the `linspace()` function, but here, the values are spaced logarithmically. See the DeCaria text for more example on this!\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "# Indexing and subsetting arrays\n", "\n", "Specific elements in an array can be accessed by indexing or subsetting Python NumPy arrays, similar to that of lists/tuples. For multidimensional arrays, the different dimensions are seperated by commas. The first index often refers to the row of the array, while the second index refers to the column. For 3 dimensional arrays, the 3rd index would represent the height, and so on...\n", "\n", "⚠️ Note: *Technically*, subsetting an array and saving it to a variable does not create a new copy of it, essentially it is just a pointer to the original array. This ultimately saves memory for the computer, which can be important when working with large data sets. This does not change anything for the purposes of this class, more or less this is just good to know. This is referred to as a *shallow* copy. If you must copy an array, you can use the `np.copy()` function, but this is rarely needed. \n", "\n", "Here are some example on how to index arrays wich is similar to indexing tuples/lists. In the most part should be review... ;-)\n" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0 2 4 6 8 10]\n" ] } ], "source": [ "seq_array = np.arange(0,11,2)\n", "print(seq_array)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "6\n" ] } ], "source": [ "print(seq_array[3])" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 6 8 10]\n" ] } ], "source": [ "print(seq_array[3:])" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10\n" ] } ], "source": [ "print(seq_array[-1])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "And some striding examples..." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]\n" ] } ], "source": [ "seq_array = np.arange(0,21,1) \n", "print(seq_array)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0 2 4 6 8 10]\n" ] } ], "source": [ "print(seq_array[0:12:2])" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0]\n" ] } ], "source": [ "print(seq_array[::-1])" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[20 18 16 14 12 10 8 6 4 2 0]\n" ] } ], "source": [ "print(seq_array[::-2])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And you get the idea of striding...!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "Finally, it is also possible to index with lists, which can be very useful:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0 2 4 6 8 10]\n" ] } ], "source": [ "my_list = [0,2,4,6,8,10]\n", "print(seq_array[my_list])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is useful, especially when utilizing the `where()` function. More on this later!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "Indexing multidimensional arrays is very similar to that of 1-D arrays, except that there are 2 or more dimensions that you need to consider. For example, lets say I wanted to grab the first element of a 2D array (upper left corner or the '1'):\n" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 2 3]\n", " [4 5 6]\n", " [7 8 9]]\n" ] } ], "source": [ "array_2D = np.array([[1,2,3],[4,5,6],[7,8,9]])\n", "print(array_2D)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n" ] } ], "source": [ "print(array_2D[0,0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "# Do it yourself #1\n", "\n", "1) What if I want to grab the top middle index (the '2')?\n", "\n", "2) What is I wanted to grab the entire middle row (4, 5, 6)?\n", "\n", "3) What if I wanted to subset for the numbers 5, 6, 7, 8?\n", "\n", "4) What if we wanted to grab the left middle value of our array (the '4')?\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "# Broadcasting arrays\n", "\n", "After defining an array, we can use a technique referred to as *broadcasting* to perform mathematical expressions or other Python functions. Think of this as if you are telling Python to broadcast a command to an audience, with this audience being all of the elements within your array. Some examples:\n", " " ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 2 3]\n", " [4 5 6]\n", " [7 8 9]]\n" ] } ], "source": [ "print(array_2D)" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 2 4 6]\n", " [ 8 10 12]\n", " [14 16 18]]\n" ] } ], "source": [ "print(array_2D * 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " This works with other mathematical functions like addition, division, substraction, ect...." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can also broadcast to specific elements within an array as well..." ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[15 16]\n", " [18 19]]\n" ] } ], "source": [ "print(array_2D[1:,1:] + 10)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 1 4]\n", " [16 25]]\n" ] } ], "source": [ "print(array_2D[:2,:2]**2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Arrays can also be added and subtracted together..." ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[ 2 4 6]\n", " [ 8 10 12]\n", " [14 16 18]]\n" ] } ], "source": [ "array1 = np.array([[1,2,3],[4,5,6],[7,8,9]])\n", "array2 = np.array([[1,2,3],[4,5,6],[7,8,9]])\n", " \n", "array3 = array1 + array2\n", " \n", "print(array3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "# Explicit and implicit loops\n", "\n", "For more complicated expressions, especially those that require multiple lines of code, we can use the `for` loop construct to go through elements in our array. Generally, this is less efficient, and so it should only be used when absolutely necessary.\n", "\n", "⚠️ Note: If Python is your first programming language, you may find yourself using loops more often that not until you start mastering programming. As time goes on you will become a more proficient programmer, but this does not happen overnight so be patient!\n", "\n", "An example of an explicit loop:\n" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0.0\n", "0.12659245357374926\n", "0.2511479871810792\n", "0.3716624556603276\n", "0.4861967361004687\n", "0.5929079290546404\n", "0.690079011482112\n", "0.7761464642917568\n", "0.8497254299495144\n", "0.9096319953545183\n", "0.9549022414440739\n", "0.984807753012208\n", "0.998867339183008\n", "0.9968547759519424\n", "0.9788024462147787\n", "0.9450008187146685\n", "0.8959937742913359\n", "0.8325698546347714\n", "0.7557495743542583\n", "0.6667690005162917\n", "0.5670598638627709\n", "0.4582265217274105\n", "0.3420201433256689\n", "0.2203105327865408\n", "0.09505604330418244\n", "-0.03172793349806786\n", "-0.15800139597335008\n", "-0.28173255684142984\n", "-0.4009305354066138\n", "-0.5136773915734064\n", "-0.6181589862206053\n", "-0.7126941713788629\n", "-0.7957618405308321\n", "-0.8660254037844388\n", "-0.9223542941045814\n", "-0.9638421585599422\n", "-0.9898214418809327\n", "-0.9998741276738751\n", "-0.9938384644612541\n", "-0.9718115683235417\n", "-0.9341478602651068\n", "-0.881453363447582\n", "-0.8145759520503358\n", "-0.7345917086575332\n", "-0.6427876096865396\n", "-0.5406408174555974\n", "-0.4297949120891719\n", "-0.31203344569848707\n", "-0.18925124436040974\n", "-0.06342391965656452\n", "0.06342391965656492\n", "0.18925124436041013\n", "0.31203344569848745\n", "0.4297949120891715\n", "0.5406408174555978\n", "0.6427876096865391\n", "0.7345917086575334\n", "0.8145759520503356\n", "0.8814533634475821\n", "0.9341478602651067\n", "0.9718115683235418\n", "0.9938384644612541\n", "0.9998741276738751\n", "0.9898214418809328\n", "0.963842158559942\n", "0.9223542941045816\n", "0.8660254037844383\n", "0.7957618405308319\n", "0.7126941713788629\n", "0.6181589862206056\n", "0.5136773915734058\n", "0.40093053540661344\n", "0.2817325568414299\n", "0.15800139597335056\n", "0.03172793349806701\n", "-0.09505604330418282\n", "-0.22031053278654034\n", "-0.342020143325668\n", "-0.45822652172741085\n", "-0.5670598638627707\n", "-0.6667690005162913\n", "-0.7557495743542588\n", "-0.8325698546347716\n", "-0.8959937742913359\n", "-0.9450008187146683\n", "-0.9788024462147789\n", "-0.9968547759519424\n", "-0.998867339183008\n", "-0.9848077530122081\n", "-0.9549022414440737\n", "-0.9096319953545183\n", "-0.8497254299495145\n", "-0.7761464642917573\n", "-0.6900790114821116\n", "-0.5929079290546404\n", "-0.48619673610046904\n", "-0.3716624556603267\n", "-0.2511479871810788\n", "-0.1265924535737493\n", "-4.898587196589413e-16\n" ] } ], "source": [ "x = np.linspace(0,4*np.pi,100) \n", "y = np.zeros_like(x)\n", " \n", "for i, val in enumerate(x):\n", " y[i] = np.sin(val)\n", " print(y[i])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Of course we can also simplify the above code by doing the following..." ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0.00000000e+00 1.26592454e-01 2.51147987e-01 3.71662456e-01\n", " 4.86196736e-01 5.92907929e-01 6.90079011e-01 7.76146464e-01\n", " 8.49725430e-01 9.09631995e-01 9.54902241e-01 9.84807753e-01\n", " 9.98867339e-01 9.96854776e-01 9.78802446e-01 9.45000819e-01\n", " 8.95993774e-01 8.32569855e-01 7.55749574e-01 6.66769001e-01\n", " 5.67059864e-01 4.58226522e-01 3.42020143e-01 2.20310533e-01\n", " 9.50560433e-02 -3.17279335e-02 -1.58001396e-01 -2.81732557e-01\n", " -4.00930535e-01 -5.13677392e-01 -6.18158986e-01 -7.12694171e-01\n", " -7.95761841e-01 -8.66025404e-01 -9.22354294e-01 -9.63842159e-01\n", " -9.89821442e-01 -9.99874128e-01 -9.93838464e-01 -9.71811568e-01\n", " -9.34147860e-01 -8.81453363e-01 -8.14575952e-01 -7.34591709e-01\n", " -6.42787610e-01 -5.40640817e-01 -4.29794912e-01 -3.12033446e-01\n", " -1.89251244e-01 -6.34239197e-02 6.34239197e-02 1.89251244e-01\n", " 3.12033446e-01 4.29794912e-01 5.40640817e-01 6.42787610e-01\n", " 7.34591709e-01 8.14575952e-01 8.81453363e-01 9.34147860e-01\n", " 9.71811568e-01 9.93838464e-01 9.99874128e-01 9.89821442e-01\n", " 9.63842159e-01 9.22354294e-01 8.66025404e-01 7.95761841e-01\n", " 7.12694171e-01 6.18158986e-01 5.13677392e-01 4.00930535e-01\n", " 2.81732557e-01 1.58001396e-01 3.17279335e-02 -9.50560433e-02\n", " -2.20310533e-01 -3.42020143e-01 -4.58226522e-01 -5.67059864e-01\n", " -6.66769001e-01 -7.55749574e-01 -8.32569855e-01 -8.95993774e-01\n", " -9.45000819e-01 -9.78802446e-01 -9.96854776e-01 -9.98867339e-01\n", " -9.84807753e-01 -9.54902241e-01 -9.09631995e-01 -8.49725430e-01\n", " -7.76146464e-01 -6.90079011e-01 -5.92907929e-01 -4.86196736e-01\n", " -3.71662456e-01 -2.51147987e-01 -1.26592454e-01 -4.89858720e-16]\n" ] } ], "source": [ "x = np.linspace(0,4*np.pi,100) \n", "y2 = np.sin(x)\n", "print(y2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Gives you the same result..." ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.\n", " 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.\n", " 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.\n", " 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.\n", " 0. 0. 0. 0.]\n" ] } ], "source": [ "print(y2 - y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "# Other useful array-related commands\n", "\n", "Listed below are useful functions and methods that I use when working with arrays!\n", "\n", ">- `.sum()`: Computes the sum of an array\n", ">- `.mean()`: Computes the mean of an array\n", ">- `.std()`: Computes the standard deviation of an array\n", ">- `.var()`: Computes the variance of an array\n", ">- `.var()`: Computes the variance of an array\n", ">- `shape()`: Returns the shape of an array\n", ">- `size()`: Returns the number of elements in an array\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "# Reshaping, transposing, and shifting arrays\n", "\n", "There are also a number of functions available for manipulating and changing the shape of an array, or for moving elements around within an array. \n", "\n", ">- `.flatten()`: Flattens a multidimensional array to a 1-D version\n", ">- `reshape(a,ns)`: Returns a copy of an array (a) with new shape ns. ⚠️ The new shape must have the same number of elements!\n", ">- `roll(a, shift,axis)`: Moves elements of a by the amount of shift. For multidimensional arrays, the arguments axis must be provided,, which specifies the axis to roll. For 1D arrays this can be left out.\n", ">- `transpose(a)`: returns a transposed copy of a.\n", ">- `rot90(a,n)`: returns a copy of 'a' rotated clockwise by n x 90 degree. A negative 'n' will rotate 'a' counterclockwise\n", ">- `squeeze(a)`: Returns a copy of 'a' with a single-element dimensions removed (i.e a 0 x 10 array will just be 10). \n", "\n", "\n", "Create some arrays and play around with some of these functions and methods!\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "**Appending:** Elements can also be appended to arrays. For example:\n" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0 2 4 6 8 10]\n" ] } ], "source": [ "seq_array = np.arange(0,11,2)\n", "print(seq_array)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0 2 4 6 8 10 12 14]\n" ] } ], "source": [ "seq_array = np.append(seq_array,[12,14])\n", "print(seq_array)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "**Inserting:** Elements can also be inserted into an array using the `np.insert()` function. This function has arguments 'a', which is our array we are inserting into, 'ind', which is the index of 'a' that we are inserting into. 'Elements' is the last argument, which will be the elements that we will be inserting into array 'a':" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0 2 4 6 8 10 12 14]\n" ] } ], "source": [ "print(seq_array)" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0 2 24 22 20 4 6 8 10 12 14]\n" ] } ], "source": [ "seq_array = np.insert(seq_array,2,[24,22,20])\n", "print(seq_array)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "**Deleting:** Elements can be deleted from an array. The `np.delete()` function, which has arguments 'a' and 'index', can remove elements from 'a' from the specified indices. " ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0 2 4 6 8 10 12 14]\n" ] } ], "source": [ "seq_array = np.delete(seq_array,[2,3,4])\n", "print(seq_array)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "Elements within an array can also be reassigned following the syntax below:\n" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0 2 4 6 8 10]\n" ] } ], "source": [ "seq_array = np.arange(0,11,2)\n", "print(seq_array)" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0 2 4 99 8 10]\n" ] } ], "source": [ "seq_array[3] = 99\n", "print(seq_array)" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0 2 -999 -999 -999 10]\n" ] } ], "source": [ "seq_array[2:5] = [-999,-999,-999]\n", "print(seq_array)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "# Stacking and splitting arrays\n", "\n", "NumPy arrays can also be combined to form a new, multidimensional array or they can be splitted into multiple 'subarrays'.\n", "\n", "**Stacking:** Multiple arrays can be stacked horizontally (by column) or vertically (by row) to form a single array. This can be done using the `np.vstack()` or `np.hstack()` functions. An example of a `np.vstack` function can be seen below:\n" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1 2 3]\n", " \n", "[4 5 6]\n", " \n", "[7 8 9]\n" ] } ], "source": [ "array1 = np.array([1,2,3])\n", "array2 = np.array([4,5,6])\n", "array3 = np.array([7,8,9])\n", " \n", "print(array1)\n", "print(' ')\n", "print(array2)\n", "print(' ')\n", "print(array3)" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1 2 3]\n", " [4 5 6]\n", " [7 8 9]]\n" ] } ], "source": [ "array_2D = np.vstack((array1,array2,array3))\n", "print(array_2D)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "**Splitting:** Arrays can also be seperated into subarrays using the `np.split()`, `np.hsplit()`, & `np.vsplit()` functions. Each of these has arguments for the array we are splitting 'a' and the number of subarrays we want to split our main array into. A `np.vsplit()` example can be seen below:\n" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[array([[1, 2, 3]]), array([[4, 5, 6]]), array([[7, 8, 9]])]\n" ] } ], "source": [ "arrays = np.vsplit(array_2D,3)\n", "print(arrays)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "**Merging:** Finally, two 1-D arrays can be merged together to form a single, multidimensional array using the `np.meshgrid(array1,array2)` function that has arguments of array1 (first array) and array2 (second array):\n" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [], "source": [ "lon = np.linspace(-119,-110,10)\n", "lat = np.linspace(41,50,10)\n", " \n", "x2d, y2d = np.meshgrid(lon,lat)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What happens when we do this?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "\n", "# Logical operations with arrays\n", "\n", "The `np.where` function provides a way for the programmer to search through an array and determine which elements meet a certain criteria. This function then returns indices of our array where these conditions are met. For example, lets say we have a 3 x 3 array (2D):\n" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [], "source": [ "array_2D = np.array([[3,2,0],[4,-4,-10],[-1,4,11]])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using the `np.where` function, lets determine which indices have elements that are less than 0:" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(array([1, 1, 2]), array([1, 2, 0]))\n" ] } ], "source": [ "negative_indices = np.where(array_2D < 0)\n", "print(negative_indices)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Did this work? Lets check!" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ -4 -10 -1]\n" ] } ], "source": [ "print(array_2D[negative_indices])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "We can also add multiple conditions using the where statement....\n" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[-10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7\n", " 8 9]\n" ] } ], "source": [ "x = np.arange(-10,10,1)\n", "idx = np.where((x > -5) & (x < 5))\n", "print(x)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Do this work?" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[-4 -3 -2 -1 0 1 2 3 4]\n" ] } ], "source": [ "print(x[idx])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

\n", "\n", "# Do it yourself #2\n", " \n", "1) Replace all negative numbers within the array below with a NaN\n", "\n", " array([0, -1.2, 2, -1, 4.9, -1, 6.1, -1, 8, -1])\n", "\n", "
\n", "\n", "2) Create a sequence that goes from 20 to 0 with intervals of 2\n", "\n", "
\n", "\n", "3) Create a 10 by 10 array that goes from 0 and ends at 99.\n", "\n", "
\n", "\n", "4) Compute the mean, min and max of our 10 by 10 array that we just created.\n", "\n", "
\n", "\n", "5) Check the data type of our newly created array.\n", "\n", "
\n", "\n", "6) What indices are greater than or equal to 40 but less than 50 in our 10 by 10 array?\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "

\n", "\n", "# Want more practice!?\n", "Check out the following webpages:
\n", "https://www.tutorialspoint.com/numpy/index.htm
\n", "https://www.w3schools.com/python/default.asp (left navigation bar)
\n", "
\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.6.7" } }, "nbformat": 4, "nbformat_minor": 4 }