6️⃣🧮 NumPy ufunc (Universal Functions)
Estimated reading: 3 minutes 282 views

NumPy ufunc Create Function – Define Your Own Vectorized ufuncs

Introduction – Why Create Custom ufuncs in NumPy?

While NumPy provides many built-in universal functions (ufuncs) like add, subtract, and sqrt, sometimes you need custom behavior—such as a domain-specific formula or a multi-step transformation.

Using np.frompyfunc() or np.vectorize(), you can create your own ufuncs that behave just like NumPy’s built-ins: they work on entire arrays, support broadcasting, and improve code readability.

By the end of this guide, you’ll:

  • Understand how to build custom NumPy ufuncs
  • Use frompyfunc() and vectorize() for vectorized function creation
  • Handle multi-input and multi-output functions
  • Know when to use (and not use) custom ufuncs

Step 1: Create ufunc Using np.frompyfunc()

import numpy as np

def custom_add(x, y):
    return x + y

add_ufunc = np.frompyfunc(custom_add, 2, 1)

a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
print(add_ufunc(a, b))

Explanation:

  • 2 → number of input arguments
  • 1 → number of outputs
  • Works element-wise on a and b
    Output:
[5 7 9]

Step 2: Create ufunc with np.vectorize()

def custom_power(x):
    return x ** 3 + 2

vec_power = np.vectorize(custom_power)

arr = np.array([1, 2, 3])
print(vec_power(arr))

Explanation:

  • Converts regular function to act element-wise on NumPy arrays
  • Automatically infers number of inputs/outputs
    Output:
[  3 10 29]

Step 3: Multi-Input Custom ufunc Example

def weighted_sum(x, y, w):
    return x * w + y * (1 - w)

weighted = np.vectorize(weighted_sum)

x = np.array([10, 20, 30])
y = np.array([1, 2, 3])
w = 0.75

print(weighted(x, y, w))

Output:

[7.75 15.5 23.25]

Step 4: Multi-Output Custom ufuncs

def div_mod(a, b):
    return divmod(a, b)

multi_output = np.vectorize(div_mod)

a = np.array([10, 20, 30])
b = np.array([3, 7, 5])

quotients, remainders = multi_output(a, b)
print("Quotients:", quotients)
print("Remainders:", remainders)

Output:

Quotients: [3 2 6]
Remainders: [1 6 0]

Performance Note

MethodProsCons
np.frompyfunc()True ufunc, returns objectSlower, lacks type info
np.vectorize()Simple, returns native dtypeStill uses Python loops under the hood

Important: These methods provide convenience, not performance gains over vectorized NumPy functions. Use NumPy built-ins or numba for speed-critical tasks.


When Should You Create Custom ufuncs?

Use when:

  • No built-in NumPy function fits your logic
  • You want to apply element-wise operations cleanly
  • You need broadcasting behavior on custom logic

Avoid when:

  • You need high-performance processing
  • You can refactor your logic using existing NumPy functions

Summary – Recap & Next Steps

Creating ufuncs in NumPy allows you to extend vectorization to your own functions, keeping code clean, readable, and broadcast-compatible. While not a performance boost, they offer tremendous convenience for element-wise logic.

Key Takeaways:

  • Use frompyfunc(func, nin, nout) for explicit ufuncs
  • Use vectorize(func) for quick vectorization with native types
  • Supports multi-input and multi-output operations
  • Best for readability and simplicity, not speed

Real-world relevance: Used in data preprocessing, simulation modeling, and custom math transformations in NumPy pipelines.


FAQs – NumPy Custom ufuncs

What’s the difference between frompyfunc() and vectorize()?
frompyfunc() returns object arrays; vectorize() preserves native data types.

Are custom ufuncs faster than Python loops?
No. They use Python under the hood. For speed, use NumPy built-ins or numba.

Can I return multiple outputs from a ufunc?
Yes, especially with np.vectorize(), which unpacks into multiple arrays.

Do custom ufuncs support broadcasting?
Yes, they follow NumPy’s broadcasting rules.

Is vectorize() the same as JIT compilation?
No. vectorize() improves syntax, not performance. Use numba for JIT.


Share Now :
Share

NumPy ufunc Create Function

Or Copy Link

CONTENTS
Scroll to Top