{ "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": { "execution": { "iopub.execute_input": "2026-05-21T16:53:20.038254Z", "iopub.status.busy": "2026-05-21T16:53:20.037914Z", "iopub.status.idle": "2026-05-21T16:53:20.083680Z", "shell.execute_reply": "2026-05-21T16:53:20.083384Z", "shell.execute_reply.started": "2026-05-21T16:53:20.038234Z" } }, "outputs": [], "source": [ "import numpy as np\n", "\n", "\n", "data = np.arange(10)" ] }, { "cell_type": "code", "execution_count": 2, "id": "1dbba2ed", "metadata": { "execution": { "iopub.execute_input": "2026-05-21T16:53:20.084245Z", "iopub.status.busy": "2026-05-21T16:53:20.084130Z", "iopub.status.idle": "2026-05-21T16:53:20.087759Z", "shell.execute_reply": "2026-05-21T16:53:20.087474Z", "shell.execute_reply.started": "2026-05-21T16:53:20.084233Z" } }, "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": { "execution": { "iopub.execute_input": "2026-05-21T16:53:20.088152Z", "iopub.status.busy": "2026-05-21T16:53:20.088077Z", "iopub.status.idle": "2026-05-21T16:53:20.090729Z", "shell.execute_reply": "2026-05-21T16:53:20.090438Z", "shell.execute_reply.started": "2026-05-21T16:53:20.088145Z" } }, "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": { "execution": { "iopub.execute_input": "2026-05-21T16:53:20.091279Z", "iopub.status.busy": "2026-05-21T16:53:20.091207Z", "iopub.status.idle": "2026-05-21T16:53:20.093624Z", "shell.execute_reply": "2026-05-21T16:53:20.093325Z", "shell.execute_reply.started": "2026-05-21T16:53:20.091272Z" } }, "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": { "execution": { "iopub.execute_input": "2026-05-21T16:53:20.094136Z", "iopub.status.busy": "2026-05-21T16:53:20.094028Z", "iopub.status.idle": "2026-05-21T16:53:20.103803Z", "shell.execute_reply": "2026-05-21T16:53:20.103430Z", "shell.execute_reply.started": "2026-05-21T16:53:20.094130Z" } }, "outputs": [ { "data": { "text/plain": [ "(array([ 0.89717849, -0.08453415, 0.47501459, 2.06944527, 0.79612329,\n", " 0.08853817, -1.71143689, -0.50690937]),\n", " array([-1.09552325, -0.95675894, 1.62991171, 1.4845231 , -0.60235054,\n", " -0.5913064 , 0.1492617 , -0.1944142 ]))" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "\n", "\n", "rng = np.random.default_rng()\n", "x = rng.normal(size=8)\n", "y = rng.normal(size=8)\n", "x, y" ] }, { "cell_type": "code", "execution_count": 6, "id": "c4d855dc", "metadata": { "execution": { "iopub.execute_input": "2026-05-21T16:53:20.106477Z", "iopub.status.busy": "2026-05-21T16:53:20.105777Z", "iopub.status.idle": "2026-05-21T16:53:20.109218Z", "shell.execute_reply": "2026-05-21T16:53:20.108906Z", "shell.execute_reply.started": "2026-05-21T16:53:20.106468Z" } }, "outputs": [ { "data": { "text/plain": [ "array([ 0.89717849, -0.08453415, 1.62991171, 2.06944527, 0.79612329,\n", " 0.08853817, 0.1492617 , -0.1944142 ])" ] }, "execution_count": 6, "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": 7, "id": "0dcd2cad", "metadata": { "execution": { "iopub.execute_input": "2026-05-21T16:53:20.109547Z", "iopub.status.busy": "2026-05-21T16:53:20.109482Z", "iopub.status.idle": "2026-05-21T16:53:20.111185Z", "shell.execute_reply": "2026-05-21T16:53:20.110968Z", "shell.execute_reply.started": "2026-05-21T16:53:20.109541Z" } }, "outputs": [], "source": [ "data = x * 5" ] }, { "cell_type": "code", "execution_count": 8, "id": "b4e1fe68", "metadata": { "execution": { "iopub.execute_input": "2026-05-21T16:53:20.111614Z", "iopub.status.busy": "2026-05-21T16:53:20.111546Z", "iopub.status.idle": "2026-05-21T16:53:20.113821Z", "shell.execute_reply": "2026-05-21T16:53:20.113563Z", "shell.execute_reply.started": "2026-05-21T16:53:20.111607Z" } }, "outputs": [ { "data": { "text/plain": [ "array([ 4.48589247, -0.42267073, 2.37507295, 10.34722634, 3.98061647,\n", " 0.44269087, -8.55718444, -2.53454686])" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "data" ] }, { "cell_type": "code", "execution_count": 9, "id": "94dd3bf3", "metadata": { "execution": { "iopub.execute_input": "2026-05-21T16:53:20.114330Z", "iopub.status.busy": "2026-05-21T16:53:20.114269Z", "iopub.status.idle": "2026-05-21T16:53:20.115906Z", "shell.execute_reply": "2026-05-21T16:53:20.115662Z", "shell.execute_reply.started": "2026-05-21T16:53:20.114323Z" } }, "outputs": [], "source": [ "remainder, whole_part = np.modf(x)" ] }, { "cell_type": "code", "execution_count": 10, "id": "30b968a0", "metadata": { "execution": { "iopub.execute_input": "2026-05-21T16:53:20.116325Z", "iopub.status.busy": "2026-05-21T16:53:20.116253Z", "iopub.status.idle": "2026-05-21T16:53:20.118621Z", "shell.execute_reply": "2026-05-21T16:53:20.118402Z", "shell.execute_reply.started": "2026-05-21T16:53:20.116318Z" } }, "outputs": [ { "data": { "text/plain": [ "array([ 0.89717849, -0.08453415, 0.47501459, 0.06944527, 0.79612329,\n", " 0.08853817, -0.71143689, -0.50690937])" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "remainder" ] }, { "cell_type": "code", "execution_count": 11, "id": "e21e6d05", "metadata": { "execution": { "iopub.execute_input": "2026-05-21T16:53:20.119039Z", "iopub.status.busy": "2026-05-21T16:53:20.118896Z", "iopub.status.idle": "2026-05-21T16:53:20.121472Z", "shell.execute_reply": "2026-05-21T16:53:20.121250Z", "shell.execute_reply.started": "2026-05-21T16:53:20.119031Z" } }, "outputs": [ { "data": { "text/plain": [ "array([ 0., -0., 0., 2., 0., 0., -1., -0.])" ] }, "execution_count": 11, "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": 12, "id": "ddd32da7", "metadata": { "execution": { "iopub.execute_input": "2026-05-21T16:53:20.121799Z", "iopub.status.busy": "2026-05-21T16:53:20.121741Z", "iopub.status.idle": "2026-05-21T16:53:20.124125Z", "shell.execute_reply": "2026-05-21T16:53:20.123846Z", "shell.execute_reply.started": "2026-05-21T16:53:20.121793Z" } }, "outputs": [], "source": [ "out = np.zeros_like(data)" ] }, { "cell_type": "code", "execution_count": 13, "id": "c87fe9f8", "metadata": { "execution": { "iopub.execute_input": "2026-05-21T16:53:20.124614Z", "iopub.status.busy": "2026-05-21T16:53:20.124454Z", "iopub.status.idle": "2026-05-21T16:53:20.127157Z", "shell.execute_reply": "2026-05-21T16:53:20.126881Z", "shell.execute_reply.started": "2026-05-21T16:53:20.124602Z" } }, "outputs": [ { "data": { "text/plain": [ "array([ 5.48589247, 0.57732927, 3.37507295, 11.34722634, 4.98061647,\n", " 1.44269087, -7.55718444, -1.53454686])" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.add(data, 1)" ] }, { "cell_type": "code", "execution_count": 14, "id": "3b8c4ead", "metadata": { "execution": { "iopub.execute_input": "2026-05-21T16:53:20.127717Z", "iopub.status.busy": "2026-05-21T16:53:20.127621Z", "iopub.status.idle": "2026-05-21T16:53:20.129860Z", "shell.execute_reply": "2026-05-21T16:53:20.129640Z", "shell.execute_reply.started": "2026-05-21T16:53:20.127706Z" } }, "outputs": [ { "data": { "text/plain": [ "array([ 5.48589247, 0.57732927, 3.37507295, 11.34722634, 4.98061647,\n", " 1.44269087, -7.55718444, -1.53454686])" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.add(data, 1, out=out)" ] }, { "cell_type": "code", "execution_count": 15, "id": "b3804bfb", "metadata": { "execution": { "iopub.execute_input": "2026-05-21T16:53:20.130179Z", "iopub.status.busy": "2026-05-21T16:53:20.130120Z", "iopub.status.idle": "2026-05-21T16:53:20.132318Z", "shell.execute_reply": "2026-05-21T16:53:20.132054Z", "shell.execute_reply.started": "2026-05-21T16:53:20.130173Z" } }, "outputs": [ { "data": { "text/plain": [ "array([ 5.48589247, 0.57732927, 3.37507295, 11.34722634, 4.98061647,\n", " 1.44269087, -7.55718444, -1.53454686])" ] }, "execution_count": 15, "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 exponential of all elements in the input array\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", "
\n", " \n", "**Note:**\n", "\n", "A complete overview of binary universal functions can be found in [Universal functions (ufunc)](https://numpy.org/doc/stable/reference/ufuncs.html).\n", "
" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.13 Kernel", "language": "python", "name": "python313" }, "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.13.0" }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 5 }