Introduction to NumPy Universal Functions

PythonPythonBeginner
Practice Now

This tutorial is from open-source community. Access the source code

Introduction

In this lab, we will explore the basics of NumPy Universal Functions (ufuncs). Ufuncs are functions that operate on ndarrays in an element-by-element fashion, supporting array broadcasting, type casting, and other standard features. We will learn about the different methods of ufuncs, broadcasting rules, type casting rules, and how to override ufunc behavior.

Note: You can write code in 08-universal-functions.ipynb. Some printing operations are omitted in the steps, and you can print output as needed.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("`Python`")) -.-> python/BasicConceptsGroup(["`Basic Concepts`"]) numpy(("`NumPy`")) -.-> numpy/ArrayManipulationGroup(["`Array Manipulation`"]) python(("`Python`")) -.-> python/ControlFlowGroup(["`Control Flow`"]) python(("`Python`")) -.-> python/DataStructuresGroup(["`Data Structures`"]) python(("`Python`")) -.-> python/FunctionsGroup(["`Functions`"]) python(("`Python`")) -.-> python/ModulesandPackagesGroup(["`Modules and Packages`"]) python(("`Python`")) -.-> python/ObjectOrientedProgrammingGroup(["`Object-Oriented Programming`"]) python(("`Python`")) -.-> python/DataScienceandMachineLearningGroup(["`Data Science and Machine Learning`"]) numpy(("`NumPy`")) -.-> numpy/ArrayBasicsGroup(["`Array Basics`"]) numpy(("`NumPy`")) -.-> numpy/IndexingandSlicingGroup(["`Indexing and Slicing`"]) numpy(("`NumPy`")) -.-> numpy/MathandStatisticsGroup(["`Math and Statistics`"]) python/BasicConceptsGroup -.-> python/comments("`Comments`") numpy/ArrayManipulationGroup -.-> numpy/reshape("`Reshape`") python/BasicConceptsGroup -.-> python/variables_data_types("`Variables and Data Types`") python/BasicConceptsGroup -.-> python/numeric_types("`Numeric Types`") python/ControlFlowGroup -.-> python/conditional_statements("`Conditional Statements`") python/DataStructuresGroup -.-> python/lists("`Lists`") python/DataStructuresGroup -.-> python/tuples("`Tuples`") python/FunctionsGroup -.-> python/function_definition("`Function Definition`") python/ModulesandPackagesGroup -.-> python/importing_modules("`Importing Modules`") python/ObjectOrientedProgrammingGroup -.-> python/classes_objects("`Classes and Objects`") python/ObjectOrientedProgrammingGroup -.-> python/polymorphism("`Polymorphism`") python/ObjectOrientedProgrammingGroup -.-> python/encapsulation("`Encapsulation`") python/DataScienceandMachineLearningGroup -.-> python/numerical_computing("`Numerical Computing`") python/FunctionsGroup -.-> python/build_in_functions("`Build-in Functions`") numpy/ArrayBasicsGroup -.-> numpy/1d_array("`1D Array Creation`") numpy/ArrayBasicsGroup -.-> numpy/multi_array("`Multi-dimensional Array Creation`") numpy/ArrayBasicsGroup -.-> numpy/data_array("`Data to Array`") numpy/IndexingandSlicingGroup -.-> numpy/basic_idx("`Basic Indexing`") numpy/IndexingandSlicingGroup -.-> numpy/bool_idx("`Boolean Indexing`") numpy/IndexingandSlicingGroup -.-> numpy/fancy_idx("`Fancy Indexing`") numpy/MathandStatisticsGroup -.-> numpy/math_ops("`Math Operations`") subgraph Lab Skills python/comments -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} numpy/reshape -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} python/variables_data_types -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} python/numeric_types -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} python/conditional_statements -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} python/lists -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} python/tuples -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} python/function_definition -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} python/importing_modules -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} python/classes_objects -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} python/polymorphism -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} python/encapsulation -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} python/numerical_computing -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} python/build_in_functions -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} numpy/1d_array -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} numpy/multi_array -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} numpy/data_array -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} numpy/basic_idx -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} numpy/bool_idx -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} numpy/fancy_idx -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} numpy/math_ops -.-> lab-85705{{"`Introduction to NumPy Universal Functions`"}} end

Basic Arithmetic Operations

The basic ufuncs operate on scalars, and the simplest example is the addition operator. Let's see how we can use the addition operator to add two arrays element-wise.

import numpy as np

## Create two arrays
arr1 = np.array([0, 2, 3, 4])
arr2 = np.array([1, 1, -1, 2])

## Add the arrays element-wise
result = arr1 + arr2

## Print the result
print(result)

Output:

array([1, 3, 2, 6])

Ufunc Methods

Ufuncs have four methods: reduce, accumulate, reduceat, and outer. These methods are useful for performing operations on arrays. Let's take a look at the reduce method.

import numpy as np

## Create an array
arr = np.arange(9).reshape(3, 3)

## Reduce the array along the first axis
result = np.add.reduce(arr, 1)

## Print the result
print(result)

Output:

array([ 3, 12, 21])

Output Type Determination

The output of a ufunc is not necessarily an ndarray if all input arguments are not ndarrays. The output type can be determined based on the input types and the rules of type casting. Let's see an example.

import numpy as np

## Create an array
arr = np.arange(9).reshape(3, 3)

## Perform multiplication and specify the output type
result = np.multiply.reduce(arr, dtype=float)

## Print the result
print(result)

Output:

array([ 0., 28., 80.])

Broadcasting

Broadcasting is a powerful feature of ufuncs that allows operations to be performed on arrays with different shapes. The broadcasting rules determine how arrays with different shapes are treated during operations. Let's see an example.

import numpy as np

## Create two arrays
arr1 = np.array([1, 2, 3])
arr2 = np.array([[1], [2], [3]])

## Multiply the arrays
result = arr1 * arr2

## Print the result
print(result)

Output:

array([[1, 2, 3],
       [2, 4, 6],
       [3, 6, 9]])

Type Casting Rules

Type casting is done on the inputs of a ufunc when there is no core loop implementation for the input types provided. The casting rules determine when a data type can be safely cast to another data type. Let's see an example.

import numpy as np

## Check if int can be safely cast to float
result = np.can_cast(np.int, np.float)

## Print the result
print(result)

Output:

True

Overriding Ufunc Behavior

Classes, including ndarray subclasses, can override how ufuncs act on them by defining certain special methods. This allows for customization of ufunc behavior. Let's see an example.

import numpy as np

## Define a custom class
class MyArray(np.ndarray):
    def __add__(self, other):
        print("Custom add method called")
        return super().__add__(other)

## Create an instance of the custom class
arr = MyArray([1, 2, 3])

## Perform addition
result = arr + 1

## Print the result
print(result)

Output:

Custom add method called
[2 3 4]

Summary

In this lab, we learned about the basics of NumPy Universal Functions (ufuncs). We explored the different methods of ufuncs, broadcasting rules, type casting rules, and how to override ufunc behavior. Ufuncs are a powerful tool for performing element-wise operations on arrays efficiently.

Other Python Tutorials you may like