{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h1>6. Arrays</h1>\n",
    "\n",
    "<h2>10/11/2023</h2>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": []
   },
   "source": [
    "<h2>6.0 Last Time...</h2>\n",
    "\n",
    "<ul>\n",
    "    <li>A <b>module</b> is a library of Python source code that gives access to new variables and functions.</li>\n",
    "    <li>Modules can be imported as whatever name you like.</li>\n",
    "    <li>A <b>raise</b> statement lets you define your own error conditions and stop code when they're met.</li>\n",
    "    <li>A <b>try/except</b> block will let you fix common issues that would otherwise result in exceptions.</li>\n",
    "</ul>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2>6.1 Creating Arrays</h2>\n",
    "\n",
    "An <b>array</b> is similar to a list, but has a lot of additional functionality! \n",
    "<ul>\n",
    "    <li>all elements are of the same type (this speeds up operations)</li>\n",
    "    <li>multi-dimensional arrays clearly supported</li>\n",
    "    <li>array operations are supported (like matrix multiplication!)</li>\n",
    "</ul>\n",
    "\n",
    "Using an array requires NumPy - remember to import it at the start of your code!\n",
    "\n",
    "The easiest way to create an array is to take a preexisting list and convert it into an array using NumPy's <b>array</b> function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[90, 123, 43], [123, 1432, 534]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "# Start with a predefined list.\n",
    "\n",
    "mylist = [[90,123,43],[123,1432,534]]\n",
    "print(mylist)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[  90  123   43]\n",
      " [ 123 1432  534]]\n"
     ]
    }
   ],
   "source": [
    "# Now let's make this a 2D array:\n",
    "\n",
    "a = np.array(mylist)\n",
    "\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2>6.2 Initializing Arrays</h2>\n",
    "\n",
    "Just like when we were building lists, sometimes you know the size and shape of the array you'd like to build, but not the individual contents.\n",
    "\n",
    "In those cases, you can create an array of zeroes where non-zero values will eventually be filled in."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0. 0.]\n",
      " [0. 0.]\n",
      " [0. 0.]]\n"
     ]
    }
   ],
   "source": [
    "# Let's use the zeros() function to make a 3x2 array.\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "x = np.zeros((3,2))\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "One of the more important ways we used lists previously was with the range() function, which counted up from zero to one less than the integer in parentheses. NumPy has an equivalent array version to save time: arange()."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 1 2 3 4 5 6 7 8 9]\n"
     ]
    }
   ],
   "source": [
    "# Use arange() to create an array of 10 elements\n",
    "# that starts from 0 and counts up through 9.\n",
    "\n",
    "import numpy as np # recall you only have to import once!\n",
    "\n",
    "a = np.arange(10)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]\n"
     ]
    }
   ],
   "source": [
    "# Note that you can also have a float version of arange:\n",
    "a = np.arange(10.0)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2>6.3 Array Indexing</h2>\n",
    "\n",
    "Just like with lists, arrays start counting at 0, and you can use negative numbers to start counting backwards (e.g., -1 refers to the last element in the array).\n",
    "\n",
    "We can also slice arrays, which is a process very similar to slicing lists:\n",
    "<ul>\n",
    "    <li>The element numbers are separated by a colon.</li>\n",
    "    <li><b>Inclusive</b> lower limit, <b>exclusive</b> upper limit.</li>\n",
    "    <li>If one of the limits is omitted, the range is extended to the end of the range (so if the lower limit is omitted, the range extends to the very beginning of the array)</li>\n",
    "    <li>To specify all elements, use a colon by itself.</li>\n",
    "</ul>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3.2\n"
     ]
    }
   ],
   "source": [
    "# Let's create a 1D array.\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "a = np.array([2, 3.2, 5.5, -6.4, -2.2, 2.4])\n",
    "\n",
    "print(a[1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 3.2  5.5 -6.4]\n"
     ]
    }
   ],
   "source": [
    "print(a[1:4])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2.  3.2 5.5]\n"
     ]
    }
   ],
   "source": [
    "print(a[:3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 2.   3.2  5.5 -6.4 -2.2  2.4]\n"
     ]
    }
   ],
   "source": [
    "print(a[:])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "So far so good... but what about multidimensional arrays? In multidimensional arrays, indexing for each dimension is separated by commas. In a 2D array, the indexing is done by [row, col]."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 2.   3.2  5.5 -6.4 -2.2  2.4]\n",
      " [ 1.  22.   4.   0.1  5.3 -9. ]\n",
      " [ 3.   1.   2.1 21.   1.1 -2. ]]\n"
     ]
    }
   ],
   "source": [
    "# Let's create a 2D array.\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "# For the following, I've played around with the spacing\n",
    "# a bit to make the dimensions more clear, but this is optional!\n",
    "\n",
    "a = np.array([[2,3.2,5.5,-6.4,-2.2,2.4],\n",
    "             [1, 22,  4, 0.1, 5.3, -9],\n",
    "             [3,  1,2.1,  21, 1.1, -2]])\n",
    "\n",
    "# This array has 3 rows and 6 columns.\n",
    "# Note that Python knew this was all part of the same line\n",
    "# even without using any special character to warn it.\n",
    "\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>Let's try some examples!</b>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[-6.4  0.1 21. ]\n"
     ]
    }
   ],
   "source": [
    "# Print the column with index 3 (the fourth column).\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "print(a[:,3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 1.  22.   4.   0.1  5.3 -9. ]\n"
     ]
    }
   ],
   "source": [
    "# Print the row with index 1 (the second row).\n",
    "\n",
    "print(a[1,:])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[22.   4.   0.1]\n"
     ]
    }
   ],
   "source": [
    "# Write a print statement that prints the slice [22, 4, 0.1].\n",
    "\n",
    "# [row, column]\n",
    "# \n",
    "print(a[1,1:4])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<h2>6.4 Take-Home Points</h2>\n",
    "<ul>\n",
    "    <li>An array is NumPy's version of a list, which allows you to work with matrices.</li>\n",
    "    <li>All elements of an array are of the same type.</li>\n",
    "    <li>You can either create a new array or convert an existing list into one.</li>\n",
    "    <li>The zeros() function is useful for initializing an array when you know the shape and size but not the contents.</li>\n",
    "    <li>The arange() function serves a similar purpose to the range() function with lists.</li>\n",
    "    <li>Similar to lists, arrays can be sliced, but arrays can be sliced across each of their dimensions.</li>\n",
    "</ul>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>Challenge Exercises:</b>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0. 0. 0. 0. 0.]\n",
      " [0. 0. 0. 0. 0.]\n",
      " [0. 0. 0. 0. 0.]\n",
      " [0. 0. 0. 0. 0.]]\n"
     ]
    }
   ],
   "source": [
    "#1. What is the code to create a 4-row, 5-column array of zeros and assign it to the variable a?\n",
    "\n",
    "import numpy as np\n",
    "\n",
    "a = np.zeros((4,5))\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[4.  2.1]\n"
     ]
    }
   ],
   "source": [
    "#2. Using array a from above, answer the following questions:\n",
    "\n",
    "a = np.array([[2,3.2,5.5,-6.4,-2.2,2.4],\n",
    "             [1, 22,  4, 0.1, 5.3, -9],\n",
    "             [3,  1,2.1,  21, 1.1, -2]])\n",
    "\n",
    "#a. What is a[:,3]?\n",
    "\n",
    "#[-6.4,0.1,21.]\n",
    "#print(a[:,3])\n",
    "\n",
    "#b. What is a[1:4,0:2]?\n",
    "#[1,22]\n",
    "#[3,1,]\n",
    "\n",
    "# print(a[1:4,0:2])\n",
    "\n",
    "#c. What will b = a[1:,2] do?\n",
    "\n",
    "b = a[1:,2] # row 1 to the end, index 2\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "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.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
