#!/usr/bin/env python # coding: utf-8 # # Functions of Arrays # # - [Download the lecture notes](https://philchodrow.github.io/PIC16A/content/np_plt/numpy_4.ipynb). # # `numpy` provides a wide range of functions for performing mathematical operations on arrays. We've already seen a few of these, such a addition, multiplication, exponentiation, and trig functions. In this lecture, we'll go into a bit more detail on entrywise functions. We'll also discuss aggregation functions that allow us to summarize large sets of numbers. # In[1]: import numpy as np # In[2]: A = np.arange(1, 11) B = np.arange(11, 21) A, B # In[3]: # Negate an array - A # In[4]: # absolute value: np.abs(-A) # In[5]: # entrywise binary arithmetic operators # all of these also work with a single scalar (e.g. replace B with 2) A + B # In[6]: A - B # In[7]: A * B # In[8]: A / B # In[9]: B ** A # In[10]: B % A # ## Mathematical Functions # # #### Trig Functions # In[11]: theta = np.linspace(0, np.pi, 3) # In[12]: print("theta = ", theta) print("sin(theta) = ", np.sin(theta)) print("cos(theta) = ", np.cos(theta)) print("tan(theta) = ", np.tan(theta)) # --- # #### Exponentials and Logarithms # In[13]: x = np.array([1, 2, 3]) # In[14]: # exponentiate a scalar 2**x # In[15]: # exponential function e^x np.exp(x) # In[16]: # natural logarithm hashtag best logarithm np.log(x) # In[17]: # base 10 and base 2 logarithms # np.log2(x) np.log10(x) # #### NaN # # When `numpy` performs an illegal mathematical operation, it will generate the value `np.nan` (for Not A Number). A common example is computing the logarithm of negative numbers. **Warnings** are generated in this case. # In[18]: x = np.array([-1, -2]) x, np.log(x) # NaN values propagate: any operation involving an NaN will generate more NaNs in the corresponding entries: # In[19]: y = np.log(x) y, y + 2 # A similar case occurs when we try to divide by zero. In this case, we get `np.inf` (for infinity): # In[20]: z = np.array([1, 1]) / np.array([0, 0]) z # `np.inf` values also propagate, e.g. `1 + np.inf = np.inf`. However, we can divide by `np.inf` values: # In[21]: 1/z # ## Plotting Functions # # We haven't yet formally introduced data visualization tools in Python. As a quick preview, let's see how to use vectorized `numpy` to easily plot mathematical functions. # In[22]: from matplotlib import pyplot as plt # #### Parabola # In[23]: x = np.linspace(-1, 1, 101) plt.plot(x, x**2) # #### Exponential and Logarithm # In[24]: plt.plot(x, np.exp(x), label = r"$y = e^x$") plt.plot(x, np.log(x), label = r"$y = \log(x)$") plt.legend() # warning comes from trying to compute np.log(-1) # #### 2-d Plotting # # It's easy to compute functions over multi-dimensional arrays. An especially common case is when we want to compute a function over one or more 2d arrays and then plot the result. Here's a simple example. We'll go into more detail on how to obtain finer control when we go more deeply into plotting in a future lecture. # In[25]: # two 100x100 arrays x = np.reshape(np.linspace(0, 2*np.pi, 10000), (100, 100)) y = np.reshape(np.linspace(0, 2*np.pi, 10000), (100, 100)).T # function of these arrays, also 100x100 z = np.sin(x) + np.cos(y) z # In[26]: plt.imshow(z)