Unit 6: Introduction to NumPy
I. Foundations of NumPy
NumPy, short for Numerical Python, is a Python library for efficient numerical computation. Its central object is the multidimensional ndarray, whose elements normally have one fixed data type and occupy a structured block of memory.
- Governing principle: NumPy performs operations on whole arrays rather than requiring explicit Python loops for every element; this approach is called vectorization.
- Import convention: NumPy is conventionally imported with the alias
np.
import numpy as np- Array dimensions: An array may have zero, one, two, or more axes.
- A scalar array has zero axes.
- A vector-like array has one axis.
- A matrix-like array has two axes.
- Higher-dimensional arrays have three or more axes.
- Homogeneous storage: Elements usually share one
dtype, such asint64,float64, orbool. - Shape convention:
shapeis a tuple giving the length of each axis; an array with three rows and four columns has shape(3, 4). - Size convention:
sizegives the total number of elements. For shape(3, 4), the size is (3 \times 4 = 12). - Axis convention: In a two-dimensional array, axis
0runs down the rows and axis1runs across the columns. - Core attributes:
a = np.array([[1, 2, 3], [4, 5, 6]])
a.ndim # 2: number of axes
a.shape # (2, 3): axis lengths
a.size # 6: total number of elements
a.dtype # integer type, platform-dependent
a.itemsize # bytes occupied by one elementII. NumPy Arrays and Python Lists — Storage and Computation
A. Arrays vs lists
Arrays and lists can both represent collections, but they differ substantially in storage rules, supported operations, and intended use.
- Python lists
- General-purpose container: A list can contain references to values of unrelated types, such as an integer, string, and Boolean.
items = [10, "NumPy", True]- Flexible structure: Lists can grow or shrink through methods such as
append(),extend(), andpop(). - Sequence behavior: Multiplication repeats a list rather than multiplying its elements.
values = [1, 2, 3]
values * 2 # [1, 2, 3, 1, 2, 3]- Elementwise work: Arithmetic across all elements generally requires a loop or comprehension.
doubled = [x * 2 for x in values]- NumPy arrays
- Numerical container: An
ndarraystores values in a regular, multidimensional structure and normally uses one data type. - Fixed size: An array’s total storage is not dynamically extended like a list; operations that appear to add elements usually create a new array.
- Elementwise behavior: Arithmetic operators act on corresponding elements.
- Numerical container: An
a = np.array([1, 2, 3])
a * 2 # array([2, 4, 6])
a + 10 # array([11, 12, 13])- Vectorization: NumPy executes many array operations in optimized compiled code, avoiding the overhead of a Python-level loop.
- Compact storage: Values of one fixed-width
dtypecan be stored more compactly than separate Python objects referenced by a list. - Multidimensional model: A single array supports dimensions directly, whereas nested lists only imitate rows and columns.
matrix = np.array([[1, 2], [3, 4]])
matrix.shape # (2, 2)- Type conversion: When given mixed numeric types, NumPy generally selects a common type capable of representing them.
a = np.array([1, 2.5, 3])
a.dtype # commonly float64- Broadcasting: Compatible arrays of different shapes may interact without manually copying values; adding scalar
5to shape(3,)applies5to all three elements. - Trade-off: Lists are preferable for heterogeneous, frequently changing collections; arrays are preferable for regular numerical data and bulk computation.
- Important distinction: An array is not a subclass of
list, even when both display similar sequences of values.
III. Constructing Structured Arrays — NumPy-Supplied Patterns
A. Array creation routines
Array creation routines generate arrays with specified shapes, values, ranges, or patterns without requiring all elements to be entered individually.
- Zero-filled arrays:
np.zeros(shape, dtype)initializes every element to zero.
z = np.zeros((2, 3), dtype=int)
# array([[0, 0, 0],
# [0, 0, 0]])shape=(2, 3)means two rows and three columns.dtype=intrequests integer elements.
- One-filled arrays:
np.ones(shape, dtype)initializes every element to one.
o = np.ones(4, dtype=float)
# array([1., 1., 1., 1.])- Constant-filled arrays:
np.full(shape, fill_value)repeats a specified value.
f = np.full((2, 2), 7)
# array([[7, 7],
# [7, 7]])-
Uninitialized arrays:
np.empty(shape, dtype)allocates storage without setting predictable values.- Its contents depend on the existing memory state.
- It is useful only when every element will be overwritten before being read.
-
Integer-like ranges:
np.arange(start, stop, step)creates evenly stepped values and excludesstop.
r = np.arange(2, 11, 2)
# array([ 2, 4, 6, 8, 10])startis the first value, here2.stopis the excluded boundary, here11.stepis the increment, here2.
- Evenly spaced intervals:
np.linspace(start, stop, num)creates exactlynumvalues and includes both endpoints by default.
x = np.linspace(0, 1, 5)
# array([0. , 0.25, 0.5 , 0.75, 1. ])num=5fixes the number of samples.- The spacing is ((1-0)/(5-1)=0.25).
- Identity matrix:
np.eye(n)creates a square two-dimensional array with ones on the main diagonal and zeros elsewhere.
identity = np.eye(3)
# array([[1., 0., 0.],
# [0., 1., 0.],
# [0., 0., 1.]])- Shape-matching routines:
np.zeros_like(a),np.ones_like(a), andnp.full_like(a, value)derive shape and usuallydtypefrom an existing arraya. - Data-type control: Supplying
dtype=np.float32, for example, fixes each element’s representation rather than relying on inference. - Routine choice: Use
arangewhen the step is central andlinspacewhen the number of samples is central;linspaceis generally safer for fractional intervals because floating-point steps may make anarangeendpoint unintuitive.
IV. Converting Available Collections — Input and Copying
A. Arrays from existing data
NumPy can construct arrays from Python sequences and other array-like objects while inferring shape and data type from their contents.
- Basic conversion:
np.array(object)converts a sequence into a newndarray.
temperatures = [18.5, 20.0, 21.5]
a = np.array(temperatures)
a.shape # (3,)
a.dtype # commonly float64- Nested sequences: Equally sized inner sequences become dimensions of a rectangular array.
data = [[1, 2, 3], [4, 5, 6]]
matrix = np.array(data)
matrix.shape # (2, 3)
matrix.ndim # 2- Rectangular requirement: Rows intended for a standard numeric array must have consistent lengths. Ragged nested sequences do not form an ordinary two-dimensional numeric array.
- Explicit type: The
dtypeargument converts values during construction when conversion is valid.
a = np.array([1, 2, 3], dtype=float)
# array([1., 2., 3.])- Array conversion:
np.asarray(data)converts array-like input but may return the original array when no conversion is needed.np.array(data)creates a copy by default in ordinary use.np.asarray(data)is useful when avoiding an unnecessary copy is desirable.
- Copying explicitly:
a.copy()creates an independent array whose later modifications do not affecta.
a = np.array([10, 20, 30])
b = a.copy()
b[0] = 99
a # array([10, 20, 30])- Text and buffer sources: Routines such as
np.fromstring()andnp.frombuffer()can interpret structured existing data, but the caller must supply suitable separators, types, or buffer formats. - Worked conversion: A flat sequence can be reshaped when its element count matches the requested dimensions.
a = np.array([1, 2, 3, 4, 5, 6])
matrix = a.reshape(2, 3)
# array([[1, 2, 3],
# [4, 5, 6]])- The original size is
6. - The requested size is (2 \times 3=6).
- A shape such as
(4, 2)would fail because it requires eight elements.
V. Selecting Array Data — Positions, Ranges, and Conditions
A. Indexing and slicing
Indexing selects individual elements or groups of elements, while slicing selects regularly spaced ranges along one or more axes.
- Zero-based indexing: The first position is index
0; negative indices count backward from the end.
a = np.array([10, 20, 30, 40])
a[0] # 10
a[-1] # 40- Slice notation:
a[start:stop:step]includesstart, excludesstop, and advances bystep.
a[1:4:2] # array([20, 40])
a[::-1] # array([40, 30, 20, 10])- Omitted boundaries: In
a[:3], the start defaults to the beginning; ina[2:], the stop defaults to the end. - Multidimensional indexing: Comma-separated indices specify one position per axis.
m = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
m[1, 2] # 6
m[0, :] # array([1, 2, 3])
m[:, 1] # array([2, 5, 8])
m[0:2, 1:3] # array([[2, 3],
# [5, 6]])- Dimensional effect:
m[0, :]removes the indexed row axis and returns shape(3,), whereasm[0:1, :]preserves it and returns shape(1, 3). - Slice views: Basic slices commonly share memory with the source array, so assigning through the slice can modify the original.
a = np.array([1, 2, 3, 4])
part = a[1:3]
part[0] = 99
a # array([1, 99, 3, 4])- Safe independence: Use
a[1:3].copy()when changes to the selected data must not affect the source. - Boolean indexing: A Boolean mask selects elements for which the corresponding condition is
True.
a = np.array([2, 7, 4, 9])
mask = a > 5
a[mask] # array([7, 9])- Fancy indexing: An integer array or list selects specified positions, generally producing a copy rather than a basic slice view.
a[[3, 0, 2]] # array([9, 2, 4])- Assignment through selection: A scalar can be assigned to every selected location.
a[a > 5] = 0
# array([2, 0, 4, 0])- Boundary rule: Slice endpoints may extend beyond the array without raising an error, but an individual out-of-range index raises
IndexError.
Did this save you a night before the exam?
LPU Notes is free, and it stays free. Ads cover part of the server bill. The rest comes out of a student's own pocket: the domain, the storage, and keeping the site up through the weeks everyone needs it at once.
The payment button didn't load. An ad blocker or a filtered network is the usual reason. to try again.
Nothing here is ever locked, and nothing unlocks. Chip in only if it was worth it. What it pays for →