Skip to content

NumPy Universal Functions (ufuncs)

What are ufuncs?

A ufunc (universal function) is a function that performs element-wise operations on data in ndarrays. Think of them as fast, vectorized wrappers around simple functions that would otherwise take one scalar in and return one scalar out.

Examples:

  • np.sqrtnp.sqrt, np.expnp.exp, np.lognp.log
  • np.sinnp.sin, np.cosnp.cos
  • np.maximumnp.maximum, np.minimumnp.minimum

They are faster and cleaner than Python loops.

Example: sqrt

sqrt
import numpy as np
 
arr = np.array([1, 4, 9, 16])
print(np.sqrt(arr))
sqrt
import numpy as np
 
arr = np.array([1, 4, 9, 16])
print(np.sqrt(arr))

Unary vs binary ufuncs

diagram Unary vs binary ufuncs mermaid
Unary ufuncs transform one array; binary ufuncs combine two arrays element-wise into one result.

np.sqrtnp.sqrt and np.expnp.exp are unary ufuncs — they take one array. Functions like np.addnp.add or np.maximumnp.maximum are binary — they take two arrays and return one result.

Common math ufuncs

math
import numpy as np
 
x = np.array([1.0, 2.0, 3.0])
print(np.exp(x))
print(np.log(x))
print(np.log10(x))
math
import numpy as np
 
x = np.array([1.0, 2.0, 3.0])
print(np.exp(x))
print(np.log(x))
print(np.log10(x))

Trigonometric ufuncs

trig
import numpy as np
 
angles = np.array([0, np.pi/2, np.pi])
print(np.sin(angles))
print(np.cos(angles))
trig
import numpy as np
 
angles = np.array([0, np.pi/2, np.pi])
print(np.sin(angles))
print(np.cos(angles))

Comparison ufuncs

max-min
import numpy as np
 
a = np.array([1, 10, 3])
b = np.array([2, 5, 4])
 
print(np.maximum(a, b))
print(np.minimum(a, b))
max-min
import numpy as np
 
a = np.array([1, 10, 3])
b = np.array([2, 5, 4])
 
print(np.maximum(a, b))
print(np.minimum(a, b))

A ufunc that returns two arrays

Most ufuncs return one array, but a few — like np.modfnp.modf — return more than one. It splits a float array into fractional and whole-number parts:

modf
import numpy as np
 
arr = np.array([4.5, -8.1, 2.25])
remainder, whole_part = np.modf(arr)
print("remainder:", remainder)
print("whole:", whole_part)
modf
import numpy as np
 
arr = np.array([4.5, -8.1, 2.25])
remainder, whole_part = np.modf(arr)
print("remainder:", remainder)
print("whole:", whole_part)

Writing results into an existing array

Ufuncs accept an optional outout argument to write results in place instead of allocating a new array — handy for saving memory on large arrays.

out
import numpy as np
 
arr = np.array([1.0, 2.0, 3.0])
result = np.zeros_like(arr)
np.add(arr, 1, out=result)
print(result)
out
import numpy as np
 
arr = np.array([1.0, 2.0, 3.0])
result = np.zeros_like(arr)
np.add(arr, 1, out=result)
print(result)

Working with NaN values

Some ufuncs have NaN-safe variants.

nan
import numpy as np
 
arr = np.array([1.0, np.nan, 3.0])
print(np.nanmean(arr))
print(np.nansum(arr))
nan
import numpy as np
 
arr = np.array([1.0, np.nan, 3.0])
print(np.nanmean(arr))
print(np.nansum(arr))

Ufuncs + broadcasting

Ufuncs naturally work with broadcasting.

broadcast
import numpy as np
 
mat = np.array([[1, 2, 3], [4, 5, 6]])
print(np.sqrt(mat))
broadcast
import numpy as np
 
mat = np.array([[1, 2, 3], [4, 5, 6]])
print(np.sqrt(mat))

Next

Continue to: Stacking and Splitting Arrays to combine and break arrays along different axes.

🧪 Try It Yourself

Exercise 1 – Apply a Unary ufunc

Exercise 2 – A Binary ufunc

Exercise 3 – NaN-safe Aggregation

If this helped you, consider buying me a coffee ☕

Buy me a coffee

Was this page helpful?

Let us know how we did