{ "cells": [ { "cell_type": "markdown", "id": "7868bd1e", "metadata": {}, "source": [ "# Universal functions (`ufunc`)\n", "\n", "A universal function, or `ufunc`, is a function that performs element-wise operations on data in `ndarrays`. They can be thought of as fast vectorised wrappers for simple functions that take one or more scalar values and produce one or more scalar results.\n", "\n", "Many `ufuncs` are simple element-wise transformations, such as [sqrt](https://numpy.org/doc/stable/reference/generated/numpy.sqrt.html) or [exp](https://numpy.org/doc/stable/reference/generated/numpy.exp.html):" ] }, { "cell_type": "code", "execution_count": 1, "id": "7d9205de", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "\n", "data = np.arange(10)" ] }, { "cell_type": "code", "execution_count": 2, "id": "1dbba2ed", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data" ] }, { "cell_type": "code", "execution_count": 3, "id": "b1a29aed", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([0. , 1. , 1.41421356, 1.73205081, 2. ,\n", " 2.23606798, 2.44948974, 2.64575131, 2.82842712, 3. ])" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.sqrt(data)" ] }, { "cell_type": "code", "execution_count": 4, "id": "18912ec7", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([1.00000000e+00, 2.71828183e+00, 7.38905610e+00, 2.00855369e+01,\n", " 5.45981500e+01, 1.48413159e+02, 4.03428793e+02, 1.09663316e+03,\n", " 2.98095799e+03, 8.10308393e+03])" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.exp(data)" ] }, { "cell_type": "markdown", "id": "f8dec7b6", "metadata": {}, "source": [ "These are called single-digit ufuncs. Others, such as [add](https://numpy.org/doc/stable/reference/generated/numpy.add.html) or [maximum](https://numpy.org/doc/stable/reference/generated/numpy.maximum.html), take two arrays (i.e. binary ufuncs) and return a single array as the result:" ] }, { "cell_type": "code", "execution_count": 5, "id": "9d8fa289", "metadata": {}, "outputs": [], "source": [ "x = np.random.randn(8)" ] }, { "cell_type": "code", "execution_count": 6, "id": "b8da90a3", "metadata": {}, "outputs": [], "source": [ "y = np.random.randn(8)" ] }, { "cell_type": "code", "execution_count": 7, "id": "a28a0433", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 0.44578824, 1.05756247, -0.91137028, -0.95006139, -0.07310552,\n", " 0.39838185, -0.07726907, -0.56184031])" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "x" ] }, { "cell_type": "code", "execution_count": 8, "id": "ed2b0f87", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([-0.63414707, -0.41705939, -0.40171689, -0.60919983, 1.5244012 ,\n", " -1.46477065, -0.12212396, 0.92888368])" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "y" ] }, { "cell_type": "code", "execution_count": 9, "id": "c4d855dc", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 0.44578824, 1.05756247, -0.40171689, -0.60919983, 1.5244012 ,\n", " 0.39838185, -0.07726907, 0.92888368])" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.maximum(x, y)" ] }, { "cell_type": "markdown", "id": "7166b405", "metadata": {}, "source": [ "Here `numpy.maximum` calculated the element-wise maximum of the elements in `x` and `y`." ] }, { "cell_type": "markdown", "id": "e31f32bd", "metadata": {}, "source": [ "Some `ufunc`, such as [modf](https://numpy.org/doc/stable/reference/generated/numpy.modf.html), a vectorised version of the built-in Python [divmod](https://docs.python.org/3/library/functions.html#divmod), return multiple arrays: the fractional and integral parts of a floating-point array:" ] }, { "cell_type": "code", "execution_count": 10, "id": "0dcd2cad", "metadata": {}, "outputs": [], "source": [ "data = x * 5" ] }, { "cell_type": "code", "execution_count": 11, "id": "b4e1fe68", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 2.22894121, 5.28781235, -4.55685142, -4.75030693, -0.36552761,\n", " 1.99190924, -0.38634536, -2.80920154])" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data" ] }, { "cell_type": "code", "execution_count": 12, "id": "94dd3bf3", "metadata": {}, "outputs": [], "source": [ "remainder, whole_part = np.modf(x)" ] }, { "cell_type": "code", "execution_count": 13, "id": "30b968a0", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 0.44578824, 0.05756247, -0.91137028, -0.95006139, -0.07310552,\n", " 0.39838185, -0.07726907, -0.56184031])" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "remainder" ] }, { "cell_type": "code", "execution_count": 14, "id": "e21e6d05", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 0., 1., -0., -0., -0., 0., -0., -0.])" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "whole_part" ] }, { "cell_type": "markdown", "id": "e85b7566", "metadata": {}, "source": [ "Ufuncs accept an optional `out` argument that allows you to transfer your results to an existing array instead of creating a new one:" ] }, { "cell_type": "code", "execution_count": 15, "id": "ddd32da7", "metadata": {}, "outputs": [], "source": [ "out = np.zeros_like(data)" ] }, { "cell_type": "code", "execution_count": 16, "id": "c87fe9f8", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 3.22894121, 6.28781235, -3.55685142, -3.75030693, 0.63447239,\n", " 2.99190924, 0.61365464, -1.80920154])" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.add(data, 1)" ] }, { "cell_type": "code", "execution_count": 17, "id": "3b8c4ead", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 3.22894121, 6.28781235, -3.55685142, -3.75030693, 0.63447239,\n", " 2.99190924, 0.61365464, -1.80920154])" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.add(data, 1, out=out)" ] }, { "cell_type": "code", "execution_count": 18, "id": "b3804bfb", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([ 3.22894121, 6.28781235, -3.55685142, -3.75030693, 0.63447239,\n", " 2.99190924, 0.61365464, -1.80920154])" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "out" ] }, { "cell_type": "markdown", "id": "ed8d8691", "metadata": {}, "source": [ "Some single-digit ufuncs:\n", "\n", "Function | Description\n", ":------- | :----------\n", "`abs`, `fabs` | calculates the absolute value element by element for integer, floating point or complex values\n", "`sqrt` | calculates the square root of each element (corresponds to `data ** 0,5`)\n", "`square` | calculates the square of each element (corresponds to `data ** 2`)\n", "`exp` | calculates the exponent ex of each element\n", "`log`, `log10`, `log2`, `log1p` | Natural logarithm (base e), log base 10, log base 2 and log(1 + x) respectively\n", "`sign` | calculates the sign of each element: `1` (positive), `0` (zero), or `-1` (negative)\n", "`ceil` | calculates the upper limit of each element (i.e. the smallest integer greater than or equal to this number)\n", "`floor` | calculates the lower limit of each element (i.e. the largest integer less than or equal to each element)\n", "`rint` | rounds elements to the nearest integer, preserving the `dtype`\n", "`modf` | returns the fractional and integer parts of the array as separate arrays\n", "`isnan` | returns a boolean array indicating whether each value is `NaN` (Not a Number)\n", "`isfinite`, `isinf` | returns a boolean array indicating whether each element is finite (not-`inf`, not-`NaN`) or infinite, respectively\n", "`cos`, `cosh`, `sin`, `sinh`, `tan`, `tanh` | regular and hyperbolic trigonometric functions\n", "`arccos`, `arccosh`, `arcsin`, `arcsinh`, `arctan`, `arctanh` | Inverse trigonometric functions\n", "`logical_not` | calculates the truth value of `not x` element by element (corresponds to `~data`)\n", "\n", "Some binary universal functions:\n", "\n", "Function | Description\n", ":------- | :----------\n", "`add` | add corresponding elements in arrays\n", "`subtract` | subtracts elements in the second array from the first array\n", "`multiply` | multiply array elements\n", "`divide`, `floor_divide` | divide or truncate the remainder\n", "`power` | increases elements in the first array to the powers specified in the second array\n", "`maximum`, `fmax` | element-wise maximum; `fmax` ignores `NaN`\n", "`minimum`, `fmin` | element-wise minimum; `fmin` ignores `NaN`\n", "`mod` | element-wise modulus (remainder of the division)\n", "`copysign` | copies the sign of the values in the second argument to the values in the first argument\n", "`greater`, `greater_equal`, `less`, `less_equal`, `equal`, `not_equal` | perform element-wise comparisons that result in a Boolean array (corresponds to the infix operators `>`, `>=`, `<`, `<=`, `==`, `!=`)\n", "`logical_and` | calculates the element-wise truth value of the logical operation AND (`&`)\n", "`logical_or` | calculates the element-wise truth value of the logical operation OR (`|`)\n", "`logical_xor` | calculates the element-wise truth value of the logical operation XOR (`^`)\n", "\n", "