NumPy Basics: Arrays & Operations Guide
NumPy Basics: Arrays & Operations Guide
Common universal functions or ufuncs provided by NumPy include operations like np.sin, np.exp, and np.sqrt, which perform elementwise mathematical operations on arrays. For example, np.sin computes the sine of each element in an input array, np.exp calculates the exponential, and np.sqrt computes the square root. These functions allow for fast computation over array elements without writing explicit loops .
In 1D arrays, elements are accessed like regular lists: a[3] retrieves the fourth element, and slices a[3:7] access a subarray. In 2D arrays, indexing uses two indices separated by a comma: M[1, 2] accesses an element in the second row and third column. Boolean indexing allows filtering based on conditions: a[a % 2 == 0] retrieves even numbers. Fancy indexing uses lists of indices: idx = [0,2]; a2[idx, idx] selects elements at (0,0) and (2,2).
NumPy's ndarray provides several advantages over Python lists: it supports efficient elementwise operations due to vectorization, is generally more memory efficient, and allows for faster computation of array operations. Additionally, ndarrays support powerful, fast N-dimensional array objects that can handle complex mathematical operations with better performance than traditional Python lists .
NumPy arrays enable aggregation operations such as sum, mean, min, max, and others, performed over specified axes or the entire array. For example, a2.sum(axis=0) computes the sum of elements column-wise, and a2.mean(axis=1) calculates the mean of elements row-wise. These operations are optimized for performance and allow for concise computations over large datasets .
To create a 2D array of zeros in NumPy, you can use the np.zeros function: np.zeros((2, 3)), which creates a 2D array with two rows and three columns filled with zeros. To create an array with equally spaced values, np.linspace is used: np.linspace(0, 1, 5), which generates five equally spaced values between 0 and 1 .
Fancy indexing in NumPy allows for indexing arrays using integer arrays or lists, enabling access to multiple array elements non-sequentially, unlike standard sequential and slice-based access. For example, given a2 = np.array([[1,2,3],[4,5,6],[7,8,9]]), fancy indexing with idx = [0, 2] and a2[idx, idx] selects diagonal elements (0,0) and (2,2), which are elements 1 and 9. This flexible indexing mode facilitates complex data manipulation .
Broadcasting in NumPy allows operations between arrays of different shapes by automatically expanding the smaller array along its dimensions. An example of broadcasting is adding a 1D array to each row of a 2D array: for instance, if M is a 3x3 matrix M = np.array([[1,2,3],[4,5,6],[7,8,9]]), and a 1D array np.array([1,0,1]) is added to it, broadcasting will expand the 1D array so it can be added to each row of the matrix M .
NumPy achieves memory efficiency and faster elementwise operations through vectorization, which allows operations to be performed on entire arrays without explicit looping. This is achieved by optimizing low-level implementations for arrays, utilizing CPU SIMD instructions and minimizing the overhead associated with standard Python operations; all of which contribute to improved performance over Python lists that often require loops or comprehension for similar operations .
Vectorization in NumPy significantly boosts computational performance by enabling batch operations on data arrays without the need for explicit loops. It leverages efficient low-level C and Fortran subroutines, utilizing CPU architecture capabilities, like SIMD, to accelerate processing, particularly advantageous for large datasets. This approach reduces the overhead of Python loops, optimizing both speed and memory usage .
Reshaping in NumPy can be accomplished using the reshape method, which, for instance, transforms a 1D array into a 2D array: a = np.arange(12), a.reshape((3, 4)) changes it into a 3x4 array. Transposing is achieved using the .T attribute which flips a matrix along its diagonal; for example, M.T, where M = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), results in the transposed matrix swapping rows and columns .