NumPy Arrays and Vectorized Computing
IntermediateLesson 1 of 8 in Data Analysis with Python Course
What you will learn
- Build NumPy arrays from Python data and with NumPy's creation functions, describe an array by its shape and data type, and choose and convert data types without losing information by accident.
- Explain what a NumPy array is and how it differs from a listDescribe an array by its dimensions, shape, size and data type, and explain why arrays behave and perform differently from Python lists.
- Create arrays from lists and with NumPy's creation functionsTurn lists into arrays and generate filled arrays, number ranges and evenly spaced grids with the shape and type you need.
- Choose, inspect and convert data typesRead and set an array's dtype, predict the type NumPy chooses, and convert between types while avoiding truncation, overflow and lost missing values.
- Explain what a NumPy array is and how it differs from a list
- Pick out single values, rows, columns and blocks; select by lists of positions or by conditions; and know when a selection shares its data with the original array.
- Index and slice one- and two-dimensional arraysUse positions and slices, one per axis, to read and change elements, rows, columns and blocks.
- Select by lists of positions and tell views from copiesSelect any elements, rows or columns with integer arrays, and predict whether a result shares memory with the original array.
- Filter with conditions using boolean masks and np.whereBuild true/false masks from comparisons, combine them, and use them to filter, count, replace and choose values.
- Index and slice one- and two-dimensional arrays
- Rearrange the same values into a new shape, swap rows and columns, add or remove axes of length 1, and join or split arrays along an axis.
- Change an array's shape and swap its axesReshape, flatten and transpose arrays, and add or remove axes of length 1, while predicting the order of the values.
- Join and split arraysCombine arrays along an existing or a new axis, and cut an array into pieces, checking that shapes fit.
- Change an array's shape and swap its axes
- Write calculations on whole arrays instead of element-by-element loops, apply NumPy's universal functions, and combine arrays of different shapes with the broadcasting rules.
- Compute element by element instead of loopingUse arithmetic and comparison operators on whole arrays, and know how they handle shapes, division by zero and in-place updates.
- Apply universal functions to whole arraysUse NumPy's element-wise math functions, including rounding and two-array functions, and handle values outside a function's domain.
- Combine arrays of different shapes with broadcastingApply the broadcasting rules to predict whether two shapes combine and what shape results, and fix shape errors by adding an axis.
- Compute element by element instead of looping
- Reduce arrays to totals, means, extremes, spreads, medians and counts, for the whole array or along a chosen axis, and handle missing values and subsets correctly.
- Aggregate a whole array or along one axisCompute sums, means, extremes, positions, running totals and spreads for the whole array or per row or column, and predict the shape of the result.
- Use medians, percentiles, sorting and unique valuesDescribe the center and spread of data with order-based statistics, sort values and related arrays, and count distinct values.
- Summarize data with missing values and conditionsFind, count, drop and fill missing values, use NaN-aware aggregations, and summarize only the values that meet a condition or belong to a group.
- Aggregate a whole array or along one axis
- Create a seeded random number generator, draw reproducible samples from common distributions, shuffle and sample data, and estimate results with vectorized simulations.
- Draw reproducible random samples with a GeneratorCreate a Generator with a seed, draw integers, decimals, normal values and samples from a list, shuffle data, and keep results reproducible.
- Run vectorized simulationsEstimate probabilities and long-run behavior by drawing all random values at once and summarizing them with array operations.
- Draw reproducible random samples with a Generator
NumPy Arrays study guide
1Create arrays and control their data types
Numerical data becomes easier to work with when its structure and storage type are clear. Build arrays from existing values or from a planned shape, then read their dimensions, element count, and dtype. Choose creation functions that match your input, and see how conversion, rounding, overflow, and missing values affect what the array actually stores. These choices determine whether later calculations retain the information you need.
1.1 Explain what a NumPy array is and how it differs from a list
NumPy stores numerical data in arrays so that one expression can work on many values. Import it with import numpy as np; the short name np is the usual way to call its functions.
Read an array's structure
An ndarray is a rectangular grid whose elements share one data type. A dimension is also called an axis. Start with a small table:
import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6]])
Its attributes answer four different questions:
| Attribute | Meaning | Value for a |
|---|---|---|
ndim | Number of axes | 2 |
shape | Length of each axis | (2, 3) |
size | Total elements | 6 |
dtype | Type of each element | Usually int64 on a 64-bit computer |
Axis 0 indexes rows; axis 1 indexes columns. A data table with one row per person and columns for height, mass, and age would have shape (100, 3) for 100 people. The product of the shape entries gives the size.
A vector has no row or column axis
np.array([2, 4, 6, 8]) has shape (4,) and one axis. The comma makes this a one-entry tuple. Shape (1, 4) has two axes: one row and four columns. Shape (4, 1) also has two axes, but four rows and one column. These arrays contain four values, yet behave differently when combined with other arrays. np.array(7) is a zero-dimensional array: its shape is () and its ndim is 0.
Arrays change the meaning of operators
A list is a general Python container. An array is designed for calculations on matching positions.
| Expression | Result |
|---|---|
[1, 2, 3] * 2 | [1, 2, 3, 1, 2, 3] |
np.array([1, 2, 3]) * 2 | array([2, 4, 6]) |
[1, 2] + [3, 4] | [1, 2, 3, 4] |
np.array([1, 2]) + np.array([3, 4]) | array([4, 6]) |
In the array addition, 1 pairs with 3 and 2 pairs with 4. The array stays the same size.
Why numerical arrays are efficient
A newly created numerical array stores same-typed values together in memory. NumPy runs the loop through these values in compiled code, avoiding a separate Python-level operation for every number. A million float64 values occupy 8,000,000 bytes of element storage, available as a.nbytes on an array of that size. A Python list also stores references to Python objects, so it needs substantially more space. Performance gains depend on the calculation and computer.
Array size does not grow through an in-place append method. np.append(a, value) allocates a new array. For data collected one value at a time, build a Python list and convert once. Nested input must be rectangular: np.array([[1, 2], [3]]) raises ValueError because its row lengths differ.
Recognize displayed results
print(np.array([1, 2, 3])) shows [1 2 3]. An interactive display uses array([1, 2, 3]). For np.array([5, 6])[0] on a 64-bit computer, NumPy 2 displays np.int64(5); it participates in arithmetic as the number 5.
Key Takeaways
- Shape gives the length of each axis; size counts all elements.
- A 1-D shape such as
(4,)differs from a 2-D row or column. - Array arithmetic acts on values at matching positions.
- Numerical arrays store one dtype and support efficient compiled calculations.
- Nested input must have equal-length rows.
1.2 Create arrays from lists and with NumPy's creation functions
Choose a creation function by asking what you know: the actual values, a shape and fill value, a step size, or a required number of points. That choice makes the code express how the data should be built.
Start from values or a shape
np.array([3, 1, 4]) creates a vector. A list of equal-length lists creates a table. Pass the values as one sequence; np.array(1, 2, 3) does not supply three elements correctly.
| Function | Example | What it creates |
|---|---|---|
np.zeros | np.zeros((3, 4)) | Three rows of four zeros |
np.ones | np.ones((2, 3)) | Two rows of three ones |
np.full | np.full((2, 2), 7) | A 2-by-2 array filled with 7 |
np.empty | np.empty((3, 4)) | Reserved, uninitialized storage |
For a multidimensional shape, the parentheses matter. np.zeros((2, 3)) passes one tuple. In np.zeros(2, 3), Python sends 3 as the dtype argument, which causes a type error. Zeros and ones use float64 by default; full infers its dtype from the fill value. Add dtype=int when you need whole-number storage.
empty does not promise zeros or meaningful starting values. Read from it only after assigning every element you will use. zeros is a simpler choice when an initial zero has meaning.
Choose a step or choose a point count
np.arange(start, stop, step) follows the stepping idea of Python's range. np.arange(2, 11, 3) gives [2 5 8]: start at 2 and add 3 while staying below 11. With one argument, np.arange(5) starts at 0 and gives [0 1 2 3 4].
Floating-point steps can give surprising endpoints. For example, np.arange(1, 1.3, 0.1) includes the displayed value 1.3 because binary rounding affects the calculation of the sequence. For a decimal grid with a fixed point count, use linspace:
grid = np.linspace(0, 1, 5)
# array([0. , 0.25, 0.5 , 0.75, 1. ])
Both endpoints are included by default. Five points make four gaps. Ten points between 0 and 1 make nine gaps, so their spacing is about 0.111; steps of 0.1 need 11 points.
Reuse an existing structure
np.zeros_like(a), np.ones_like(a), and np.full_like(a, value) create new arrays with a's shape and dtype. The inherited dtype matters: filling an integer template with a decimal can lose the decimal part unless you request a floating dtype. np.eye(3) creates a square identity array with ones on the diagonal and zeros elsewhere.
Allocate a data table once
For rainfall in millimeters at three stations over four weeks:
rain = np.zeros((3, 4))
rain[0] = [12.0, 0.0, 5.5, 8.0]
The first assignment fills one row and preserves shape (3, 4). If the number of readings is known, reserving the full table avoids repeatedly allocating larger arrays. If the amount of input is unknown, accumulate values in a list and call np.array when collection is finished.
Key Takeaways
- Pass a multidimensional shape as a tuple.
arangespecifies a step;linspacespecifies a point count.linspaceincludes both endpoints by default.emptymust be filled before its values are used.- The like-functions inherit both shape and dtype.
- Allocate a known final shape once.
1.3 Choose, inspect and convert data types
An array's dtype controls what it can store and how much memory each value needs. Choosing the right type also prevents calculations from quietly losing information.
Inspect the storage type
int64 holds 64-bit whole numbers, float64 holds binary floating-point numbers, and bool holds true/false values. Unicode dtypes such as <U5 store text with a maximum character length. a.itemsize is the bytes per element; a.nbytes is a.size * a.itemsize. A float64 uses 8 bytes and has about 15 significant decimal digits of precision.
On typical 64-bit computers, whole-number input uses 64-bit integers. NumPy 2 also uses that default on 64-bit Windows. Decimal input normally gives float64.
Inference chooses one shared type
np.array([1, 2.5]) becomes [1. 2.5]: the integer is represented as a float. np.array([True, 2]) becomes [1 2]. Mixing numbers and text can turn the entire array into text, so a label such as 'n/a' can make later arithmetic fail. Inspect dtype when apparently numerical data will not add or multiply.
Convert deliberately
astype returns a converted copy:
x = np.array([1.7, -1.7, 2.5])
whole = x.astype(int)
# array([ 1, -1, 2])
This conversion cuts toward zero; it does not round. np.round(x).astype(int) gives [2 -2 2] because exact halves round to the nearest even value. Text such as '1.5' converts with astype(float), but 'n/a' raises ValueError. Clean placeholders before conversion.
Assignments use the destination's dtype. After a = np.array([1, 2, 3]), assigning a[0] = 9.9 stores 9 without warning. Converting the entire array to float first lets later assignments retain decimals.
Fixed-width integers can overflow
An int8 holds values from −128 to 127; a uint8 holds 0 to 255. Adding two uint8 arrays containing 250 and 10 produces 4 through wraparound. Multiplying an int8 array containing 100 by 2 produces −56. A Python integer that cannot fit the array type, such as 300 added to an int8 array in NumPy 2, raises OverflowError instead. Widen small integer types before calculations that can exceed their range.
Division and approximate decimals
| Operation | Example | Result |
|---|---|---|
| True division | np.array([7, 8]) / 2 | [3.5 4.] |
| Floor division | np.array([7, -7]) // 2 | [3 -4] |
| Remainder | np.array([7, -7]) % 2 | [1 1] |
Floor division rounds down toward negative infinity, which differs from truncation for negative results. True division returns floating-point results for integer inputs.
Many decimal fractions are approximations in binary. 0.1 + 0.2 == 0.3 is false; np.isclose compares corresponding values with a tolerance, and np.allclose gives one whole-array answer.
The missing marker np.nan is floating-point. Integer arrays cannot store it. np.array([1, 2, np.nan]) therefore becomes floating-point; converting missing values to integers does not repair them and can yield meaningless results.
Key Takeaways
- One dtype governs every element, including values assigned later.
astype(int)truncates toward zero; rounding is a separate step.- Small fixed-width integers can overflow during arithmetic.
- Use tolerance-based comparisons for approximate decimals.
- NaN needs a floating-point dtype.
2Select and filter data in arrays
An analysis rarely needs every value in exactly its original order. Select individual positions, regular slices, arbitrary records, or entries that satisfy a condition. Track whether a result shares memory with its source before editing it. Boolean masks then let the same selection rule support filtering, replacement, counts, and proportions, while preserving complete records when that is what your question needs.
2.1 Index and slice one- and two-dimensional arrays
Indexing locates values by position. Slicing selects a regular run of positions. In a table, write one selector for each axis so the code says both which rows and which columns you need.
Read a vector
For a = np.array([10, 20, 30, 40, 50]), position 0 contains 10 and position −1 contains 50. A slice has the form start:stop:step, with the stop excluded:
| Selection | Result |
|---|---|
a[1:4] | [20 30 40] |
a[::2] | [10 30 50] |
a[::-1] | [50 40 30 20 10] |
a[3:10] | [40 50] |
Leaving out start or stop extends to the relevant end. A slice can run beyond the array and be shortened automatically. A single invalid position, such as a[5], raises IndexError.
Give each table axis its own selector
m = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
m[1, 2] reads row 1, column 2, giving 6. The comma separates axes. A colon alone selects the full axis: m[0, :] gives the first row [1 2 3], and m[:, 1] gives the second column [2 5 8]. For a block, m[:2, 1:] selects rows 0 and 1 and columns 1 and 2, giving [[2 3] [5 6]].
Avoid treating repeated square-bracket indexing as interchangeable with comma indexing. m[1][2] happens to locate the same scalar as m[1, 2]. But m[:][0] first takes all rows and then selects the first row. It does not select the first column, which is m[:, 0].
Predict which axes remain
A single integer selector removes its axis. A slice retains its axis even when only one position is selected. Thus m[:, 1] has shape (3,), while m[:, 1:2] has shape (3, 1). Both select 2, 5, and 8, but only the second keeps a column axis. This difference becomes important when subtracting or multiplying arrays with other shapes.
The same rule extends beyond tables. If t.shape is (2, 3, 4), t[0] has shape (3, 4), t[0, 1] has shape (4,), and t[:, :, 0] has shape (2, 3). Any trailing axes omitted from the index are selected in full.
Change the selected positions
Assignment through an index writes into the existing array. a[1:3] = 0 replaces both selected values with zero; the scalar is applied throughout the selection. m[0] = [0, 0, 0] replaces a complete row. The assigned values must fit the selection's shape and are converted to its dtype.
For four students and three tests:
scores = np.array([[78, 85, 92], [64, 70, 58],
[88, 91, 95], [72, 68, 80]])
scores[2] is the third student's [88 91 95]. scores[:, -1] gives the final-test results [92 58 95 80]. scores[1:3, :2] gives [[64 70] [88 91]]: two students, each retaining two test columns.
Key Takeaways
- Indexes start at 0; negative indexes count from the end.
- Slices exclude the stop and can be shortened at an array boundary.
- Use comma-separated selectors for separate axes.
- An integer removes an axis; a slice retains it.
- Assignment through an index changes the selected values.
2.2 Select by lists of positions and tell views from copies
A selection can share its data with the original array or own independent data. Knowing which one you have prevents edits to a small selection from unexpectedly changing a larger table.
Distinguish an alias, a view, and a copy
| Code | Relationship | Effect of changing b |
|---|---|---|
b = a | Two names for one object | Changes a |
b = a[2:5] | A slice view sharing data | Changes the corresponding part of a |
b = a[2:5].copy() | Independent data | Leaves a unchanged |
For a = np.arange(6) and b = a[2:5], assigning b[0] = 99 makes a equal to [0 1 99 3 4 5]. The first position of the view refers to position 2 in the original. This differs from slicing a Python list, which makes a new list.
Copy before editing when the original must remain intact. A small retained view can also keep a large original data buffer alive; copying that small piece lets it stand independently.
Select arbitrary positions
Fancy indexing uses an integer list or array. It allows reordered and repeated positions:
a = np.array([10, 20, 30, 40, 50])
a[[4, 0, 0]]
# array([50, 10, 10])
For m = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), m[[0, 2]] selects the first and third rows. m[:, [2, 0]] selects the last and first columns in that order, giving [[3 1] [6 4] [9 7]].
Two integer lists in one index select paired coordinates. m[[0, 2], [1, 2]] pairs row 0 with column 1 and row 2 with column 2, producing [2 9]. It does not take all combinations. To get the block formed by both rows and both columns, use:
m[np.ix_([0, 2], [1, 2])]
# array([[2, 3], [8, 9]])
Selecting the rows first and then the columns, m[[0, 2]][:, [1, 2]], gives the same block.
Reading and assigning behave differently
Fancy indexing and boolean filtering return copies. If c = a[[0, 1]], changing c[0] leaves a unchanged. But a[[0, 1]] = -1 writes directly into those original positions. A saved selection and an assignment through an index are different operations.
This also explains why chained edits can fail to reach the source. In a[[0, 1]][0] = -1, the first selection is already a temporary copy. The final write changes that temporary array, not a.
Check sharing directly
np.shares_memory(x, y) checks whether two arrays overlap in memory. It returns true for an ordinary nonempty slice and false for a fancy-indexed copy. The base attribute can identify a backing owner, but it need not identify the array you most recently sliced. If a = np.arange(6), b = a[2:5], and c = b[0:2], then c.base is a is true and c.base is b is false. Use shares_memory when the question is specifically whether two arrays share data.
Key Takeaways
- Assignment aliases an array; a basic slice shares its data.
- Use
.copy()for an independent selection. - Fancy indexing preserves the requested order and allows repeats.
- Two integer index lists pair coordinates;
np.ix_selects all combinations. - Fancy-indexed reads copy, but direct indexed assignments update the source.
- Use
np.shares_memoryto test sharing between arrays.
2.3 Filter with conditions using boolean masks and np.where
A boolean mask records which values satisfy a condition. Once a mask exists, the same true/false decisions can select values, count events, or choose replacements.
Build and apply a mask
t = np.array([18.5, 22.0, 15.2, 25.8, 21.1])
warm = t > 20
t[warm]
# array([22. , 25.8, 21.1])
The comparison produces [False True False True True]. Boolean indexing keeps the true positions and returns a copy. A 1-D mask used on an axis must have the same length as that axis.
To combine conditions, use & for and, | for or, and ~ for not. Put parentheses around each comparison:
comfortable = (t > 18) & (t < 23)
t[comfortable]
# array([18.5, 22. , 21.1])
Python's and and or try to get one truth value from an entire array and fail for multi-element arrays. Omitting the parentheses also changes how Python groups the expression because bitwise operators bind before comparisons.
Count, measure, or test conditions
True contributes 1 and False contributes 0. warm.sum() is 3 and warm.mean() is 0.6, the fraction of days above 20 °C. np.count_nonzero(warm) also counts true entries. warm.any() asks whether at least one day is warm; warm.all() asks whether every day is warm.
These operations answer different questions from t[warm].mean(), which calculates the average temperature among warm days. The mean of a mask measures a share; the mean of selected measurements retains the measurement's unit.
Replace values or choose between branches
Assignment through a mask updates the selected positions. With t2 = t.copy(), the line t2[t2 < 16] = 16 raises low readings to 16. np.clip(t, 16, 25) returns a new array bounded at both ends, [18.5 22. 16. 25. 21.1].
np.where(condition, x, y) builds a new result taking x at true positions and y at false positions. np.where(t > 20, 'warm', 'cool') supplies a label at every original position. In contrast, filtering shortens the result. With a condition alone, np.where(t > 20) returns a tuple of index arrays, here (array([1, 3, 4]),).
Keep values or keep complete records
A same-shape mask on a 2-D array extracts matching elements into one flat vector. In m[m > 5], the row structure is lost. To retain whole records, derive one boolean per row from a column:
scores = np.array([[78, 85, 92], [64, 70, 58],
[88, 91, 95], [72, 68, 80]])
scores[scores[:, 2] >= 90]
# array([[78, 85, 92], [88, 91, 95]])
Find missing values explicitly
NaN does not compare equal even to itself. Equality and ordering comparisons with NaN are false; inequality is true. Thus neither x == np.nan nor x != np.nan identifies present and missing entries correctly. np.isnan(x) marks missing positions, and x[~np.isnan(x)] keeps present values.
Key Takeaways
- A mask holds one true/false decision per tested position.
- Combine comparisons with parenthesized
&,|, and~. - A mask sum counts matches; a mask mean gives their fraction.
- Use a row-length mask to filter whole records.
np.wherechooses values at every position.- Use
np.isnanto find NaN.
3Reshape, transpose and join arrays
A useful array shape expresses how the data belongs together: months within quarters, measurements within records, or batches within a larger collection. Rearrange values with reshape, swap axis roles with transpose, and add length-one axes when a vector needs a row or column role. Joining and splitting then combine or separate those groups, with shape checks that keep the intended structure intact.
3.1 Change an array's shape and swap its axes
Changing shape changes how values are grouped into axes. Reshaping, transposing, and adding an axis do different jobs, even when some of them produce the same final shape.
Reshape without changing the element count
a = np.arange(6)
r = a.reshape(2, 3)
# array([[0, 1, 2], [3, 4, 5]])
The default order fills one row at a time: the last axis changes fastest. Reshaping the same values to (3, 2) gives [[0 1] [2 3] [4 5]]. The product of the new dimensions must equal the original size. Twelve elements fit (3, 4) but not (5, 3).
One dimension can be -1, letting NumPy infer its length. np.arange(12).reshape(-1, 3) gives four rows of three; reshape(2, -1) gives two rows of six. Two unknown dimensions are not allowed because their individual lengths cannot be determined from the total alone.
Transpose swaps the axes
For r above, r.T is [[0 3] [1 4] [2 5]], with shape (3, 2). Each old column is now a row. That arrangement differs from r.reshape(3, 2), even though the resulting shapes match.
| Operation | What happens to r |
|---|---|
r.reshape(3, 2) | Reads values row by row and regroups them |
r.T | Swaps row and column roles |
A transpose is useful when the next operation needs the opposite axis order. A reshape is useful when a sequence already has a meaningful grouping, such as months grouped into quarters.
A 1-D transpose does not make a column
v = np.arange(3) has only one axis, so v.T still has shape (3,). Add an axis explicitly:
column = v[:, np.newaxis] # shape (3, 1)
row = v[np.newaxis, :] # shape (1, 3)
v.reshape(-1, 1) and np.expand_dims(v, 1) also create a column. np.squeeze(column) removes its length-one axis and returns shape (3,). Adding an axis changes no values but tells later arithmetic how they should line up.
Flattening and memory sharing
r.ravel() and r.flatten() both list values in a 1-D result. ravel returns a view when possible; flatten always copies. reshape(-1) is another way to request a 1-D arrangement, but whether it shares memory depends on the input's layout. Reshape may need a copy; transpose shares data in its array view. Use .copy() when independent storage is required.
Group monthly values into quarters
For monthly = np.array([120, 135, 150, 160, 155, 170, 180, 175, 165, 150, 140, 130]), monthly.reshape(4, 3) makes four quarter rows, each with three months. Summing each row with .sum(axis=1) gives [405 485 520 420]. The first total is 120 + 135 + 150 = 405. The reshape works because the chronological input already puts each quarter's months together.
Key Takeaways
- Reshape preserves element count and follows row-major order by default.
- One
-1dimension can be inferred. - Transpose swaps axis roles and can differ from a same-shape reshape.
- Use a new axis to turn a vector into a row or column.
flattencopies;raveland reshape can share data.
3.2 Join and split arrays
Joining combines values from several arrays. Splitting cuts one array into pieces. First decide whether the operation should extend an existing axis or introduce a new one.
Concatenate along an existing axis
np.concatenate([a, b], axis=0) joins vectors end to end. Joining [1 2] with [3 4 5] gives [1 2 3 4 5].
For two arrays each shaped (2, 3), axis 0 adds rows and gives (4, 3). Axis 1 adds columns and gives (2, 6). Only the joining axis can differ in length. Thus shapes (2, 3) and (2, 2) can join along axis 1 into (2, 5), but cannot join along axis 0 because their column counts disagree.
The arrays must be passed together as a sequence, such as [a, b]. Joining creates a new combined array and copies the inputs' data.
Stack along a new axis
For p = np.array([1, 2, 3]) and q = np.array([4, 5, 6]):
| Expression | Shape | Arrangement |
|---|---|---|
np.concatenate([p, q]) | (6,) | One longer vector |
np.stack([p, q]) | (2, 3) | One vector per row |
np.stack([p, q], axis=1) | (3, 2) | One vector per column |
stack requires equal input shapes and adds an axis. concatenate preserves the number of axes. The helper functions express common arrangements: vstack([p, q]) makes rows, hstack([p, q]) joins these 1-D inputs end to end, and column_stack([p, q]) makes columns. The 1-D behavior of hstack is why its name alone is not enough to predict a table.
Cut by boundaries or by part count
np.split(np.arange(10), [3, 7]) cuts before positions 3 and 7, yielding [0 1 2], [3 4 5 6], and [7 8 9]. The boundary positions are not part lengths.
An integer second argument instead requests equal parts: np.split(x, 3) asks for three equal pieces. Ten elements cannot be divided equally into three integer-sized pieces, so this raises ValueError. np.array_split(np.arange(10), 3) allows unequal lengths and produces 4, 3, and 3. These splitting calls return a collection of arrays, not one array with a new stacking axis.
Build a measurement table
h = np.array([1.62, 1.75, 1.80]) # meters
w = np.array([55.0, 72.5, 80.0]) # kilograms
data = np.column_stack([h, w])
Shape (3, 2) means three people with height and mass in columns. Selecting data[:, 1] / data[:, 0] ** 2 calculates mass divided by squared height for each row, giving approximately 21.0, 23.7, and 24.7 kg/m². Keeping the two measurement arrays in the same person order is essential.
If input arrives in batches, collect the batch arrays in a Python list and call concatenate once. Rejoining a growing array during every loop pass repeatedly copies its existing data.
Key Takeaways
- Concatenation extends an axis; stacking adds one.
- Nonjoining dimensions must match for concatenation.
- Use
column_stackto turn matching vectors into table columns. - Split positions are boundaries; an integer part count requests equal pieces.
array_splitpermits unequal piece lengths.- Collect batches first and join once.
4Replace loops with vectorized arithmetic, ufuncs and broadcasting
Whole-array expressions let you describe numerical work without writing a Python loop for each value. Begin with matching-position arithmetic, then apply NumPy's mathematical functions and combine different shapes through broadcasting. Reading the shapes explains which values pair and which repeat. Casting rules, invalid inputs, and division warnings also matter when a short expression performs many calculations at once.
4.1 Compute element by element instead of looping
Vectorization expresses a calculation for entire arrays. NumPy handles the repeated element-level work in compiled code, so the Python expression can stay close to the calculation you mean.
Translate a loop into matching-position arithmetic
prices = np.array([2.50, 4.00, 1.20])
qty = np.array([3, 1, 5])
line_totals = prices * qty
order_total = line_totals.sum()
The products are [7.5 4. 6.] and their sum is 17.5. Each price pairs with its own quantity. A Python loop updating a total produces the same result, but makes Python handle each pair separately.
All the arithmetic operators act element by element: +, -, *, /, //, %, and **. A scalar applies to every entry. 10 - np.array([1, 2, 3]) gives [9 8 7]; operand order still matters. Two arrays need equal shapes or compatible broadcasting shapes.
Keep element-wise and matrix products distinct
* multiplies corresponding entries. For A = np.array([[1, 2], [3, 4]]) and B = np.array([[5, 6], [7, 8]]), A * B gives [[5 12] [21 32]]. Matrix multiplication uses @ and would give [[19 22] [43 50]]. Choose * for paired measurements such as price and quantity.
Comparisons also return one answer per position
a == b produces a boolean array. It does not ask whether two arrays are equal as whole objects. An if statement needs one truth value, so if a == b: fails for multi-element results. np.array_equal(a, b) tests exact whole-array equality. For approximate decimals, np.allclose(a, b) tests agreement within tolerance.
Understand division warnings
With default NumPy error settings, floating-point division by zero produces a warning and special values:
np.array([1.0, -1.0, 0.0]) / 0
# array([ inf, -inf, nan])
np.isfinite identifies results that are neither infinite nor NaN. Integer floor division by zero instead returns integer zeros with a warning. Those zeros look finite, so inspect integer denominators with (d == 0).any() before floor division. A warning deserves attention even when the program continues.
Decide whether to update in place
a += value modifies existing storage and retains its dtype. If a is an integer array, a += 0.5 raises a casting error because the floating-point result cannot be stored under that operation's casting rule. a = a + 0.5 creates a floating-point result and binds a to it. This differs from assigning one decimal into an integer element, which can silently truncate.
Build a multi-step expression
For old = np.array([2.50, 4.00, 8.00]) and new = np.array([3.00, 3.00, 8.00]), (new - old) / old * 100 gives [20. -25. 0.]. First find each change, then divide by its original value, then express the ratio as a percentage. The signs show a rise, a fall, and no change. The original values must be nonzero for this percentage calculation.
Key Takeaways
- Vectorized operators calculate on whole arrays element by element.
*pairs entries;@performs a matrix product.- Whole-array comparisons need a single-result function.
- Check denominators and inspect division warnings.
- In-place arithmetic retains the destination dtype.
4.2 Apply universal functions to whole arrays
A universal function, or ufunc, applies a calculation separately at each array position. These functions extend vectorization beyond ordinary arithmetic to roots, logarithms, rounding, comparisons, and other numerical operations.
Choose an array-aware function
Unary ufuncs take one input. np.sqrt(np.array([1, 4, 9])) gives [1. 2. 3.], and np.abs(np.array([-2, 3])) gives [2 3]. np.exp is the exponential function, np.log is the natural logarithm, and np.log10 is the base-10 logarithm. For example, np.exp(0) is 1.0 and np.log10(1000) is 3.0.
Python's math module works on individual numbers. math.sqrt(np.array([1, 4])) cannot calculate both roots and raises a type error. Use NumPy's version for numerical arrays. Operators also call ufuncs: a + b corresponds to np.add(a, b) and a * b to np.multiply(a, b).
Compare corresponding values or reduce a whole array
Binary ufuncs take two inputs. np.maximum([1, 5, 3], [4, 2, 6]) gives [4 5 6], choosing the larger value at every position. np.minimum chooses the smaller, and np.power raises corresponding bases to powers.
np.maximum(x, 0) sets negative entries to zero in a new result. It is different from np.max(x), an aggregation that returns one largest value. For [1, 5, 3], max gives 5; maximum needs another input and retains the element-wise structure.
Round with the intended rule
| Function | Rule | Result for −2.5 |
|---|---|---|
np.floor | Down toward negative infinity | −3.0 |
np.ceil | Up toward positive infinity | −2.0 |
np.trunc | Toward zero | −2.0 |
np.round | Nearest; exact halves to even | −2.0 |
np.round(x, 2) keeps two decimal places. Exact halves follow the even rule: np.round([0.5, 1.5, 2.5]) gives [0. 2. 2.]. Binary approximation can affect decimal-looking ties, so interpret displayed decimals with their floating-point representation in mind.
Inspect values outside a function's domain
For real floating-point inputs, np.sqrt(-1.0) returns NaN with a warning, while np.log(0.0) returns negative infinity with a warning under default error settings. Unlike math.sqrt(-1), these calls do not normally halt with a domain exception. Check the inputs when the mathematical operation requires a restricted range. np.isnan marks NaN; np.isfinite marks values that are neither NaN nor infinite; np.isclose compares values with a tolerance.
Combine ufuncs into a useful calculation
For coordinate arrays x = np.array([3, 5, 8]) and y = np.array([4, 12, 15]), calculate distance from the origin with np.sqrt(x ** 2 + y ** 2). Squaring gives [9 25 64] and [16 144 225]; adding gives [25 169 289]; the roots are [5. 13. 17.]. np.hypot(x, y) calculates those distances directly.
Key Takeaways
- Ufuncs perform numerical operations at each position.
- Use NumPy functions for arrays, including roots and logarithms.
maximumcompares positions;maxreduces values.- Floor, ceiling, truncation, and rounding use different rules.
- Inspect NaN and infinity after invalid real-valued operations.
4.3 Combine arrays of different shapes with broadcasting
Broadcasting lets arrays with different shapes participate in element-wise calculations. The aligned axes determine which values pair and which repeat.
Compare dimensions from the right
Line up shapes at their right-hand ends. Each pair of axis lengths must be equal or have one length equal to 1. Missing leading axes count as length 1. A length-one axis expands conceptually to match the other length; NumPy need not copy the repeated input values.
For (4, 3) and (3,), the last lengths match at 3. The missing leading dimension acts as 1 and expands to 4. The result is (4, 3): the vector applies to every row. (4, 3) and (4,) fail because the trailing lengths 3 and 4 disagree and neither is 1. An incompatible pair raises ValueError.
Center or standardize columns
X = np.array([[1, 10], [2, 20], [3, 30]])
centered = X - X.mean(axis=0)
The column means are [2. 20.], shape (2,). They line up with the last axis of (3, 2), giving [[-1. -10.] [0. 0.] [1. 10.]]. Dividing the centered result by X.std(axis=0) standardizes each column, producing approximately −1.22, 0, and 1.22 down both columns. Each column's spread must be nonzero for this division.
Keep an axis for row calculations
Use a score table with four students and three tests:
scores = np.array([[78, 85, 92], [64, 70, 58],
[88, 91, 95], [72, 68, 80]])
scores.mean(axis=1) has shape (4,). It cannot broadcast as one mean per row against (4, 3). Preserve the removed axis:
row_mean = scores.mean(axis=1, keepdims=True)
centered = scores - row_mean
row_mean now has shape (4, 1). Its leading 4 matches the rows; its trailing 1 expands across three columns. scores.mean(axis=1)[:, np.newaxis] creates the same shape. For the row [78, 85, 92], subtracting its mean of 85 gives [-7. 0. 7.].
Use the same rule to build a table
np.arange(1, 4)[:, np.newaxis] * np.arange(1, 5) combines (3, 1) and (4,). Both arrays expand to the result shape (3, 4), producing [[1 2 3 4] [2 4 6 8] [3 6 9 12]].
Expansion can also be accidental. A (3, 1) column minus a (3,) vector creates all nine pairwise differences, shape (3, 3). If you intended three corresponding differences, make both inputs shape (3,), for example with column.ravel().
Weight each column before adding
For the same score table and w = np.array([0.2, 0.3, 0.5]), scores * w applies the three weights to every row. Summing with .sum(axis=1) gives [87.1 62.8 92.4 74.8]. The first result is 15.6 + 25.5 + 46.0 = 87.1.
Key Takeaways
- Align shapes from the right; paired lengths must match or include 1.
- A length-one axis controls the direction of expansion.
- Column summaries usually align with a table directly.
- Keep row summaries shaped as columns with
keepdims=True. - Broadcasting can create an unintended pairwise table.
- Weight columns before reducing across each row.
5Summarize arrays with aggregations along axes
A table can produce an overall total, one summary per record, or one summary per variable. Decide which axis to collapse, then choose a statistic that answers your question. Positions, running totals, and sorted ranks offer different views of the data. Missing values and conditions require their own decisions, because filtering or filling can change both which observations contribute and what the result means.
5.1 Aggregate a whole array or along one axis
An aggregation combines values into fewer results: a total, mean, extreme, or measure of spread. Choosing the axis is part of choosing the question, because it decides which groups of values are combined.
Collapse the axis you name
For a (4, 3) table with four students and three tests, an aggregation without axis uses all 12 values. scores.sum() gives one total. scores.mean(axis=0) collapses the student axis and leaves three test means. scores.mean(axis=1) collapses the test axis and leaves four student means.
scores = np.array([[78, 85, 92], [64, 70, 58],
[88, 91, 95], [72, 68, 80]])
Its overall sum is 941. The column means are [75.5 78.5 81.25]; the row means are approximately [85. 64. 91.33 73.33]. Ask which axis should disappear. Saying “axis 0 means each row” reverses the operation: axis 0 combines rows.
Choose the quantity to return
| Operation | Result type |
|---|---|
sum, prod | Total or product |
mean | Arithmetic average |
min, max | Extreme value |
argmin, argmax | Position of an extreme |
std, var | Standard deviation or variance |
Methods such as a.sum() and functions such as np.sum(a) express the same basic operation. NumPy's methods avoid the different behavior of Python's built-ins. For example, Python's sum(scores) adds row arrays to produce column totals, while scores.sum() combines all entries. Python's max(scores) tries to compare rows and raises an ambiguous-truth error.
Positions differ from values
scores.mean(axis=1).argmax() is 2: the third student has the highest mean. argmax returns the first position when maxima tie. Without an axis on a table, it returns a row-major flattened index; scores.argmax() is 8. np.unravel_index(8, scores.shape) recovers coordinate (2, 2).
Use keepdims=True when a summary must align with the original table. scores.sum(axis=1, keepdims=True) has shape (4, 1), making it suitable for one normalization value per row. Without it, the result has shape (4,).
Keep intermediate totals when order matters
np.cumsum([3, 1, 4, 1, 5]) gives [3 4 8 9 14]. Each position is the total through that point. np.cumprod([1, 2, 3, 4]) similarly gives [1 2 6 24]. np.diff([3, 1, 4, 1, 5]) gives the four neighbor changes [-2 3 -3 4]. On a table, specify axis=1 for separate running totals across rows.
State the spread convention
std and var divide the squared-deviation total by the number of values by default: ddof=0. Use ddof=1 for the sample formula, whose divisor is one smaller. For [2, 4, 4, 4, 5, 5, 7, 9], the mean is 5, the default standard deviation is 2.0, and the sample standard deviation is about 2.14. A report should make clear which convention it uses.
Key Takeaways
- The
axisargument names the axis being collapsed. - No axis means one summary across the whole array.
argminandargmaxreturn positions, including the first tied position.keepdims=Trueretains reduced axes at length 1.- Cumulative functions retain intermediate results.
- NumPy uses
ddof=0by default;ddof=1selects the sample divisor. - Prefer NumPy aggregations to Python built-ins on arrays.
5.2 Use medians, percentiles, sorting and unique values
Order-based summaries describe where values sit in a sorted distribution. Sorting also supports ranking records, but a table needs careful treatment to keep each record's fields together.
Locate the middle and the quartiles
For x = np.array([12, 15, 11, 20, 18, 14]), the sorted order is [11 12 14 15 18 20]. With six values, np.median(x) averages the middle two, 14 and 15, giving 14.5. For an odd count, the median is the one middle value.
np.percentile(x, q) takes a percentage from 0 to 100. np.quantile(x, q) takes the equivalent fraction from 0 to 1. Their default linear interpolation can give a value between observations. For six values, the 25th percentile's zero-based position is 0.25 × 5 = 1.25. That lies one quarter of the way from 12 to 14, giving 12.5. The 50th and 75th percentiles are 14.5 and 17.25, so the interquartile range is 4.75.
The median resists an extreme value more than the mean does. Adding 200 to these data moves the mean from 15.0 to about 41.4; the median moves from 14.5 to 15.0. Neither measure alone describes the whole distribution.
Choose sorted data or sorting positions
np.sort(x) returns a sorted copy. x.sort() changes x and returns None, so y = x.sort() does not put sorted values into y. For descending values, use np.sort(x)[::-1].
On a 2-D array, sorting defaults to the last axis, sorting each row independently. axis=0 sorts each column independently. Neither operation is a record sort. For tab = np.array([[3, 1], [1, 2], [2, 0]]), np.sort(tab, axis=0) gives [[1 0] [2 1] [3 2]], separating values that originally belonged together.
To preserve records, get an ordering from the key column and apply it to whole rows:
order = tab[:, 0].argsort()
ranked = tab[order]
# array([[1, 2], [2, 0], [3, 1]])
The same index order can reorder related vectors. If avg = np.array([85.0, 64.0, 91.33, 73.33]) and names = np.array(['Ana', 'Ben', 'Chen', 'Dara']), order = np.argsort(avg)[::-1] ranks the means in descending order. names[order] gives ['Chen' 'Ana' 'Dara' 'Ben'].
Count distinct values and test membership
np.unique returns sorted distinct values. With return_counts=True, it also returns corresponding counts:
colors = np.array(['red', 'blue', 'red', 'green', 'blue', 'red'])
values, counts = np.unique(colors, return_counts=True)
The outputs are ['blue' 'green' 'red'] and [2 1 3]. values[counts.argmax()] finds the most frequent value, 'red'. The count positions match the unique-value positions.
np.isin(a, allowed) returns a mask for membership in a collection. For a = np.arange(1, 6), np.isin(a, [2, 4]) gives [False True False True False], ready to select those values or their associated records.
Key Takeaways
- The median uses sorted position and resists extreme values.
- Percentiles use 0–100; quantiles use 0–1.
- Default percentile interpolation can fall between observations.
np.sortcopies; an array's.sort()mutates and returnsNone.- Use
argsortpositions to keep records and related arrays aligned. unique(..., return_counts=True)pairs distinct values with frequencies.isinbuilds a membership mask.
5.3 Summarize data with missing values and conditions
Missing data and filtered subsets need an explicit summary policy. A numerical result can be wrong even when the array operation runs successfully: a placeholder can be counted as a measurement, or an empty subset can be mistaken for a meaningful average.
Find missing values before summarizing
NaN propagates through ordinary sums and means. For x = np.array([3.0, np.nan, 5.0]), both x.sum() and x.mean() give NaN. np.nansum(x) gives 8.0 and np.nanmean(x) gives 4.0, skipping the missing position. Related functions include nanmax, nanmin, nanstd, and nanmedian. If every value is missing, nanmean returns NaN with a warning because no observed values remain.
For sensor readings in °C:
r = np.array([21.5, np.nan, 22.1, 23.0, np.nan, 21.9])
missing = np.isnan(r)
missing.sum() is 2, missing.mean() is about 0.33, and r[~missing] keeps four readings. np.nanmean(r) is 22.125, using only those four values. Comparing r == np.nan would fail to mark the missing readings.
Convert placeholder codes first
A number such as −999 may represent missing data in an input system. NumPy treats it as a real measurement until you replace it:
v = np.array([12, -999, 15, -999, 9]).astype(float)
v[v == -999] = np.nan
np.nanmean(v) # 12.0
Convert to float first because an integer array cannot store NaN. This replacement is appropriate only when −999 is defined as the missing code for those data.
Filling changes the distribution
Replacing missing temperatures with zero makes the example's mean 14.75, even though no zero-temperature measurement was observed. Filling them with the observed mean, 22.125, preserves that mean but reduces the apparent spread. A filled value is an introduced estimate, so its effect belongs in the analysis decision.
For a 2-D table D, np.nanmean(D, axis=0) summarizes each column's observed values. Each column can have a different count. To drop rows containing any missing value:
complete = ~np.isnan(D).any(axis=1)
clean_rows = D[complete]
The reduction creates one decision per row; negation retains rows with no missing entries. With D = np.array([[1., 2.], [np.nan, 4.], [5., np.nan], [7., 8.]]), this keeps [[1. 2.] [7. 8.]].
Summarize a condition or a group
For temperatures t, t[t > 20].mean() averages only days above 20 °C. In grouped data, use a matching label mask: with group = np.array(['A', 'B', 'A', 'B', 'A']) and value = np.array([10, 20, 14, 26, 12]), value[group == 'A'].mean() is 12.0 and the corresponding B mean is 23.0. Iterate over np.unique(group) to repeat this for each group.
Before summarizing a filtered subset, check mask.any(). An empty selection's mean is NaN with a warning, while its sum is 0. That zero can be a valid empty total, but it does not establish that any measurement was present.
Key Takeaways
- Ordinary sums and means propagate NaN; NaN-aware versions skip it.
- Convert defined missing codes to NaN in floating-point storage.
- Filling missing values changes the statistics.
- Row-wise missing-value tests can identify complete records.
- Combine label or condition masks with aggregations.
- Check for an empty subset before interpreting its mean.
6Generate random numbers and run simulations
Random arrays support repeatable sampling and practical experiments. Create one seeded Generator, choose a distribution and output shape, and preserve record relationships when shuffling or splitting data. In a simulation, make the trial structure explicit before calculating events or running positions. Compare results with simple exact cases, and separate ordinary sampling variation from mistakes in the code.
6.1 Draw reproducible random samples with a Generator
A random number generator supports sampling, shuffling, and simulation. A seed makes the starting state repeatable, so you can rerun an analysis while investigating its logic.
Create one Generator and reuse it
rng = np.random.default_rng(42)
NumPy recommends this Generator interface for new code. Its default bit generator is PCG64. Without a seed, default_rng() obtains fresh entropy from the operating system. Older calls such as np.random.seed and np.random.rand use shared global state; Generator objects let an analysis manage its own state directly.
Pseudorandom values come from a deterministic algorithm. The same starting state and same sequence of calls reproduce the stream in the same environment. Every draw advances the state. Creating a new Generator with seed 42 inside every loop pass restarts the stream, repeating the same initial draws instead of continuing it. Record the NumPy version and the code as well as the seed, because stream compatibility is not guaranteed across versions or all environments. For passwords or security tokens, use Python's secrets module.
Pick a distribution and an output shape
| Call | Meaning |
|---|---|
rng.random(5) | Five decimals from 0 inclusive to 1 exclusive |
rng.uniform(2, 8, size=5) | Five uniform draws over the interval from 2 to 8 |
rng.integers(1, 7, size=10) | Ten integers from 1 through 6 |
rng.normal(loc=170, scale=10, size=(3, 4)) | A 3-by-4 sample from a normal distribution |
size can be an element count or a shape tuple. For normal, loc is the distribution mean and scale is its standard deviation. A variance of 100 therefore needs scale=10. A small sample's actual mean and standard deviation need not match the distribution parameters exactly.
For integer draws, the upper bound is excluded by default. A die needs integers(1, 7), since integers(1, 6) cannot draw 6. integers(1, 6, endpoint=True) includes the upper bound and also models a die.
Sample values with or without replacement
rng.choice(['heads', 'tails'], size=5) makes five draws with replacement. A value can appear several times. For distinct sampled positions, use replace=False; requesting more positions than the population has raises ValueError. Probabilities can be supplied as p=[0.7, 0.3], in the same order as the values, and must sum to 1.
Without replacement prevents selecting an input position twice. If the input itself contains duplicate values, equal values can still appear in the sample.
Shuffle records without separating their fields
rng.shuffle(a) rearranges the existing array and returns None. rng.permutation(a) returns a shuffled copy. rng.permutation(10) gives integers 0 through 9 in random order, useful as row indexes.
For a 2-D array, the default axis is 0: complete rows move together. That keeps each observation's fields aligned. To shuffle two related arrays consistently, generate one permutation of their shared record indexes and apply it to both.
Key Takeaways
- Create a seeded Generator once and reuse its advancing state.
- Reproducibility depends on the seed, calls, and numerical environment.
- Integer draws exclude the upper bound unless
endpoint=True. - Normal
scaleis standard deviation, not variance. choicesamples with replacement by default.shufflemutates;permutationreturns a shuffled result.
6.2 Run vectorized simulations
A vectorized simulation represents repeated trials as arrays, applies the event rule to those arrays, and summarizes the results. The array shape should show what one trial contains.
Turn an event into a proportion
rng = np.random.default_rng(42)
rolls = rng.integers(1, 7, size=100_000)
estimate = (rolls == 6).mean()
The mask is true once for every observed 6. Its mean estimates the probability of that event, close to 1/6, or about 0.1667. rolls.mean() answers a different question: the average die face, close to 3.5. A fixed seed repeats an estimate; it does not make that estimate exact.
Vectorization avoids Python-level work for each draw, often making large simulations much faster than a loop. The speedup depends on the calculation, array size, and computer, so it is not a fixed property of the event.
Use one row per multi-value trial
To simulate two dice in each trial:
dice = rng.integers(1, 7, size=(100_000, 2))
totals = dice.sum(axis=1)
p_seven = (totals == 7).mean()
The table has 100,000 trial rows and two die columns. Reducing axis 1 produces one total per trial. Six of the 36 equally likely ordered pairs sum to 7, so the estimated probability should be near 6/36. Reducing axis 0 would instead give two totals across all trials and lose the trial-level event.
Larger simulations still vary
For independent trials, the standard error of an estimated proportion is:
Here is the event probability and the trial count. For a die's 6 with 100,000 trials, it is about 0.0012. A normal approximation puts about 95% of estimates within 0.0023 of 1/6. Increasing the trial count by a factor of 100 reduces standard error by a factor of 10. More draws do not correct an incorrectly coded event.
Build and inspect a random walk
steps = rng.choice([-1, 1], size=1000) draws left or right steps. walk = steps.cumsum() gives the position after each step. Its maximum and minimum locate the extreme positions visited. To find the first point at least 10 units from the start:
hit = np.abs(walk) >= 10
if hit.any():
step_count = hit.argmax() + 1
argmax locates the first true entry, but also returns 0 when every entry is false. The any() check distinguishes a real hit from no hit. Add 1 because array position 0 is the position after step 1.
For many walks, rng.choice([-1, 1], size=(5000, 1000)).cumsum(axis=1) accumulates separately along each row. walks[:, -1] selects all final positions; their mean is near 0 and standard deviation near the square root of 1,000, about 31.6.
Use permutations and exact checks
A random split of 100 records can use idx = rng.permutation(100), then data[idx[:80]] and data[idx[80:]]. The two disjoint slices of one permutation assign every record exactly once. For a simulation, compare a simple case with an exact answer, such as a die mean of 3.5, before trusting more complicated output.
Key Takeaways
- Represent one trial clearly in the array shape.
- A boolean mean estimates an event probability.
- Reduce within trials before combining results across trials.
- Standard error shrinks with the square root of trial count.
- Check for a hit before using
argmaxas a first-hit locator. - One permutation can produce disjoint random record splits.
- Validate simulation logic against an exact simple case.
NumPy Arrays examples
1Build a measurement array you can trust
14 steps
- 1IntroductionPlan the records and measurements
A measurement table needs two decisions before any calculation: what each axis represents and what kind of values must be stored. We will build a small table, inspect its shape, and choose creation and conversion methods that preserve the data.
Keep
import numpy as npat the top of the script. The namenpgives access to the NumPy functions used throughout the examples. - 2ExplanationRead a table through its axes
Create
a = np.array([[2, 4, 6], [3, 5, 7]]). The outer sequence supplies two rows; each inner sequence supplies three values.a.shapeis(2, 3),a.ndimis 2, anda.sizeis 6. Shape describes the arrangement, ndim counts axes, and size counts all entries. If each row is one record, this table contains two records with three measurements each. - 3Key InsightEqual sizes can have different structures
A length-six vector has shape
(6,). A table with one row has shape(1, 6), and a table with one column has shape(6, 1). Each contains six values, but only the last two have separate row and column axes.The trailing comma in
(6,)marks a one-entry tuple. It is useful information: the vector has one axis, so it has no separate row direction to transpose into a column. - 4ChallengePredict multiplication before running it
What are the results of
[2, 5] * 2andnp.array([2, 5]) * 2?---reveal---
The list becomes
[2, 5, 2, 5]. The array becomes[4 10]. Lists repeat their contents under integer multiplication; numerical arrays multiply the values at each position. The array keeps its shape, which makes it suitable for applying a calculation to every recorded value. - 5ExampleReserve a table with a known shape
Suppose two stations will each supply four rainfall readings in millimeters. Create
rain = np.zeros((2, 4)), then assignrain[0] = [4.0, 0.0, 3.5, 6.0].The tuple
(2, 4)is one shape argument. Zeros uses floating-point storage by default, so the reading 3.5 is retained. Reserving the final shape once avoids repeatedly copying a growing array as readings arrive. - 6TipChoose the starting fill deliberately
Use
zeroswhen initial zeros are meaningful,onesfor ones, andfull(shape, value)for another repeated value. Their names describe the starting contents.emptyonly reserves storage. Its initial values are not ready to use, so every entry must be filled before it is read. A zeros-filled table is easier to inspect while writing code that will assign only some of its entries. - 7ExplanationCount points and gaps separately
For measurement positions from 0 m through 2 m at intervals of 0.5 m, there are five points and four gaps.
np.linspace(0, 2, 5)creates those points and includes both ends.np.arange(0, 2, 0.5)uses a step and excludes the stop, so it omits 2 m. Floating-point rounding can also make decimalarangegrids surprising; uselinspacewhen the point count is the requirement. - 8ChallengeChoose a grid from its endpoints
A scan requires nine equally spaced positions from 0 cm to 4 cm, including both ends. What creation call fits, and what is the spacing?
---reveal---
Use
np.linspace(0, 4, 9). Nine points make eight gaps across 4 cm, so the spacing is 0.5 cm. A third argument of 8 would request eight points, leaving only seven gaps and producing a different interval between readings. - 9ExplanationInspect the inferred dtype
np.array([1, 2.5])becomes floating-point because one shared dtype must hold both values. Mixing a number with text can instead turn all values into text, causing arithmetic to fail.Inspect
a.dtypewhen the values do not behave as expected.a.itemsizereports the storage bytes per element; multiplying it bya.sizegivesa.nbytes, the total bytes occupied by the elements. - 10ExampleWatch an assignment discard decimals
Start with
counts = np.array([2, 4, 6]), then runcounts[0] = 3.8. The first entry becomes 3 because the existing storage remains integer.To retain later decimals, create floating-point storage first with
values = counts.astype(float).astypemakes a converted copy. It does not change the dtype of the original array or recover fractional information that an earlier assignment already discarded. - 11Key InsightConversion and rounding are separate
np.array([2.8, -2.8]).astype(int)gives[2 -2]: truncation moves toward zero.np.roundrounds to nearest, with exact halves going to even, so 2.5 rounds to 2.0.Small integer dtypes introduce a different risk. A
uint8cannot hold 260, so array arithmetic such as 250 plus 10 can wrap to 4. Widen the dtype before calculating values that may exceed its range. - 12ChallengePreserve a missing reading
You have
a = np.array([5, 7, 9])and need to mark its middle reading missing. What preparation does the array need before assigning NaN?---reveal---
Convert to floating-point storage:
a = a.astype(float), then seta[1] = np.nan. Integer storage cannot represent NaN. The result is[5. nan 9.]; substituting zero would record a numerical value instead of marking a missing measurement. - 13ChallengeCombine creation and a later update
You create
template = np.array([1, 2]), then need a same-shaped array whose values can later include 1.5 and NaN. What creation choice keeps those values possible?---reveal---
Use a floating dtype, for example
np.zeros_like(template, dtype=float). The default like-function would inherit integer storage. The shape can stay(2,), while choosing float allows both the fractional measurement and the missing-value marker. - 14RecapInspect structure before calculating
For the next array you create, inspect
shape,size, anddtypebefore applying arithmetic. Check that each axis represents the intended group of values and that storage can hold the measurements you will assign.Choose a point count or a step deliberately when generating a grid. If decimal values or NaN will appear, plan floating-point storage before writing those values into the array.
2Select records and control what edits change
16 steps
Save this lesson to follow every Walkthrough step by step.
- 1IntroductionAsk which values belong in the result
- 2ExplanationFollow start, stop, and step
- 3ExampleSelect rows and columns in one expression
- 4ChallengeKeep a column axis
- 5ExampleTrace a write through a view
- 6TipMake independence explicit
- 7ExplanationPair coordinates or choose a block
- 8ChallengeSeparate a copy from a direct assignment
- 9ExplanationTurn a condition into a selection
- 10ExampleCombine interval bounds
- 11Key InsightCount events or average their values
- 12ExampleChoose replacement or filtering
- 13ChallengeRetain complete rows
- 14TipFind NaN without equality
- 15ChallengeUpdate selected records independently
- 16RecapCheck the target of each edit
3Give values the right shape and grouping
12 steps
Save this lesson to follow every Walkthrough step by step.
- 1IntroductionMake grouping visible in the shape
- 2ExampleGroup consecutive values into periods
- 3ExplanationInfer one missing dimension
- 4ExampleSwap the meaning of rows and columns
- 5ChallengeCreate a column from a vector
- 6TipChoose flattening with editing in mind
- 7ExplanationExtend an existing axis
- 8ExampleAdd a batch axis instead
- 9ChallengeMake two measurement columns
- 10ExampleSplit by boundaries or part count
- 11ChallengeRebuild a table from row batches
- 12RecapRead shapes as data decisions
4Calculate across records without a Python loop
15 steps
Save this lesson to follow every Walkthrough step by step.
- 1IntroductionLet the expression describe the calculation
- 2ExampleMultiply paired values and total them
- 3ExplanationUse the right product operator
- 4TipCheck the destination and denominator
- 5ChallengeChoose the reference for percentage change
- 6ExplanationApply mathematical functions to arrays
- 7ExampleBuild distances in stages
- 8ChallengeCompare maximum with a reduction
- 9TipInspect rounding and invalid values
- 10ExplanationAlign shapes from their right ends
- 11ExampleKeep row means as a column
- 12Key InsightA valid broadcast can answer the wrong question
- 13ChallengePredict a broadcast result
- 14ChallengeWeight centered measurements
- 15RecapCheck values, pairing, and output shape
5Summarize the observations that answer your question
15 steps
Save this lesson to follow every Walkthrough step by step.
- 1IntroductionChoose the question before the statistic
- 2ExampleReduce the measurement axis
- 3Key InsightTrack what survives the reduction
- 4ExampleSeparate position, value, and running total
- 5ChallengeChoose the variance divisor
- 6ExampleLocate a median and percentile
- 7TipSort records through positions
- 8ChallengeRecover a label from its count
- 9ExplanationSkip missing values deliberately
- 10ExampleTranslate a missing code before averaging
- 11Key InsightFilling creates observations for the calculation
- 12ExampleBuild one completeness decision per row
- 13ChallengeRecognize an empty subset
- 14ChallengeSummarize and compare groups
- 15RecapReport what contributed to each summary
6Run a reproducible simulation from draws to results
14 steps
Save this lesson to follow every Walkthrough step by step.
- 1IntroductionGive each simulated trial a clear shape
- 2ExplanationCreate the Generator once
- 3ExampleSet integer and normal draw parameters
- 4ChallengeFind the repeated randomness bug
- 5TipChoose replacement and preserve records
- 6ExampleEstimate an event with a mask
- 7ExampleReduce within each two-die trial
- 8ChallengeChange the event to either die
- 9ExplanationExpect sampling variation
- 10ExampleAccumulate steps into a path
- 11TipCheck that the boundary was reached
- 12ChallengeSplit records exactly once
- 13ChallengeDecide what a much larger run can fix
- 14RecapCheck the model and then its precision
NumPy Arrays practice questions
Set 1: Connect selections, shapes, and summaries10 Practice Questions
Question 1 of 10
np.arange(4, 16, 5) create?Show answerHide answer
Question 2 of 10
template = np.array([2, 4, 6]), what values are created by np.full_like(template, 1.8) with the default dtype?Show answerHide answer
template as well as its shape. Filling that storage with 1.8 converts each value to 1, so all three entries are 1. Inferring a new floating dtype from the fill value would be the behavior of np.full, not this default full_like call.Question 3 of 10
a after a = np.arange(7); b = a[1:5]; c = a[[1, 4]]; b[1] = 90; c[0] = 80?Show answerHide answer
b shares data with a, and its index 1 refers to original index 2, so 90 reaches that position. The fancy-indexed c is an independent copy, so assigning 80 into it leaves a unchanged. Treating both selections as views would incorrectly put 80 into original index 1.Question 4 of 10
a = np.array([3, 6, 9, 12, 15, 18, 21]), what values does a[1:6:2] select?Show answerHide answer
Question 5 of 10
a and b have shapes (3, 2) and (3, 5). What shape does np.concatenate([a, b], axis=1) have?Show answerHide answer
(3, 7). Introducing a third dimension would require a stacking operation; concatenation extends an existing axis and does not add a new one.Question 6 of 10
x = np.array([-3.5, 2.5]), what does np.floor(x) - np.trunc(x) give?Show answerHide answer
[-4., 2.], while truncation gives [-3., 2.], so subtracting gives [-1., 0.]. Both functions agree for the positive input but differ for the negative input. Treating floor as cutting off decimals would incorrectly make the negative difference zero.Question 7 of 10
x = np.array([6., 8.]) and y = np.array([8., 15.]) in meters, keep only points at most 12 m from the origin. What are the retained distances?Show answerHide answer
np.hypot(x, y), obtaining 10 m and 17 m, then filter those distances by the 12 m limit. Only 10 m remains. Adding coordinate magnitudes gives 14 and 23, which measures a different path; clipping 17 down to 12 would replace an out-of-range distance instead of excluding the point.Question 8 of 10
x = np.array([10., np.nan, 16., np.nan, 22.]), what is the mean after replacing every NaN with zero?Show answerHide answer
Question 9 of 10
rng.choice(np.arange(5), size=6, replace=False) is called?Show answerHide answer
ValueError. Repeated draws would be possible with replacement, but that is explicitly disabled here; NumPy does not silently shrink the requested sample.Question 10 of 10
dice contains 60,000 trials of three fair dice with shape (60000, 3). What expression estimates the chance that a trial contains at least one 6?Show answerHide answer
any(axis=1) to turn each trial row into one success decision. The mean across those decisions estimates the share of trials with at least one 6. Taking the mean of all die-level comparisons estimates the chance that one die is a 6, losing the trial-level event.Set 2: Read arrays and choose the right operation10 Practice Questions
Save this lesson to see every answer and practice every set.
Question 1 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 2 of 10
d = np.array([[9, 30], [2, 80], [5, 40]]). How can you sort records by their first column, smallest first, while keeping each row together?Show answerHide answer
Save this lesson to see this answer.
Question 3 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 4 of 10
np.arange(8).reshape(2, 4).T[1]?Show answerHide answer
Save this lesson to see this answer.
Question 5 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 6 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 7 of 10
np.array([4.9, -4.9]).astype(int)?Show answerHide answer
Save this lesson to see this answer.
Question 8 of 10
v = np.array([2, 8, 11, 5, 14]), what fraction does (v >= 8).mean() return?Show answerHide answer
Save this lesson to see this answer.
Question 9 of 10
np.array([5., 8.]) and new prices are np.array([6., 6.]). What percentage changes does (new - old) / old * 100 give?Show answerHide answer
Save this lesson to see this answer.
Question 10 of 10
[batch_id, mass_kg]: d = np.array([[1, 4], [2, 9], [1, 7], [2, 5]]). What is the mean mass of batch 1 records whose mass exceeds 5 kg?Show answerHide answer
Save this lesson to see this answer.
Set 3: Trace data through several array operations10 Practice Questions
Save this lesson to see every answer and practice every set.
Question 1 of 10
np.percentile([4, 8, 12, 20], 25)?Show answerHide answer
Save this lesson to see this answer.
Question 2 of 10
x = np.array([1., 3., 5.]), what is x.var(ddof=1)?Show answerHide answer
Save this lesson to see this answer.
Question 3 of 10
a = np.array([8, 12]); a[0] = 3.7; b = a / 2?Show answerHide answer
Save this lesson to see this answer.
Question 4 of 10
m = np.arange(20).reshape(4, 5), what are the shape and values of m[1:3, 2:3]?Show answerHide answer
Save this lesson to see this answer.
Question 5 of 10
t with shape (3, 4, 5), what shape does t[1, :, 2:4] have?Show answerHide answer
Save this lesson to see this answer.
Question 6 of 10
v = np.arange(1, 13) are grouped into four consecutive three-hour periods. After swapping the period and within-period axes, what is the first row?Show answerHide answer
Save this lesson to see this answer.
Question 7 of 10
np.array_split(np.arange(14), 4) produce?Show answerHide answer
Save this lesson to see this answer.
Question 8 of 10
A = np.array([[2, 3], [4, 5]]), what does A * A return?Show answerHide answer
Save this lesson to see this answer.
Question 9 of 10
X are [2., 6.] and [8., 12.]. Each row needs its own mean subtracted. What result does the mistaken expression X - X.mean(axis=1) actually give?Show answerHide answer
Save this lesson to see this answer.
Question 10 of 10
steps contains five ±1 moves for one walk. You need the share of walks that reach at least 3 units from the start at any recorded step. What expression calculates that share?Show answerHide answer
Save this lesson to see this answer.
Set 4: Diagnose results that look plausible10 Practice Questions
Save this lesson to see every answer and practice every set.
Question 1 of 10
a has shape (6, 4) and itemsize == 8. You run b = a[::2, 1:], then c = b[:, ::2].copy(). How many bytes of element storage does c have?Show answerHide answer
Save this lesson to see this answer.
Question 2 of 10
np.array([4, 7]) * 3 produce?Show answerHide answer
Save this lesson to see this answer.
Question 3 of 10
m = np.arange(12).reshape(3, 4), what is m[[0, 2], [1, 3]]?Show answerHide answer
Save this lesson to see this answer.
Question 4 of 10
[group, reading] are [[1., 6.], [2., np.nan], [1., 10.], [2., 14.], [1., np.nan]] in d. How can you get the mean of present readings in group 1?Show answerHide answer
Save this lesson to see this answer.
Question 5 of 10
v = np.arange(5), how do v.T.shape and v[:, np.newaxis].shape compare?Show answerHide answer
Save this lesson to see this answer.
Question 6 of 10
x = np.array([-4., 2., 7.]), what does np.maximum(x, 3) produce?Show answerHide answer
Save this lesson to see this answer.
Question 7 of 10
(3, 2) table contains paired values for three records. A length-three vector offset gives one correction per record. You need each correction added to both values in its own record. What expression and result shape fit?Show answerHide answer
Save this lesson to see this answer.
Question 8 of 10
values, counts = np.unique([4, 9, 4, 2, 9, 9], return_counts=True). What does values[counts.argmax()] return?Show answerHide answer
Save this lesson to see this answer.
Question 9 of 10
D = np.array([[2., 4.], [np.nan, 6.], [8., np.nan]]), what does np.nanmean(D, axis=0) return?Show answerHide answer
Save this lesson to see this answer.
Question 10 of 10
ids = np.arange(6) and a separate measurement array have matching record order. You need four training records and two test records, with matching IDs and measurements and no overlap. What plan guarantees this?Show answerHide answer
Save this lesson to see this answer.
Set 5: Combine array tools in complete analyses10 Practice Questions
Save this lesson to see every answer and practice every set.
Question 1 of 10
Show answerHide answer
Save this lesson to see this answer.
Question 2 of 10
np.array([5, -999, 9]), where −999 means missing. You need the observed mean after adding a 0.5 correction to each present reading. What is the correct result?Show answerHide answer
Save this lesson to see this answer.
Question 3 of 10
a = np.array([2, 5, 8, 11]); b = a[1:]; c = b[[0, 2]]; b[0] = 20; c[1] = 30; a[[0, 3]] = c. What is a afterward?Show answerHide answer
Save this lesson to see this answer.
Question 4 of 10
x = np.array([1., np.nan, 4., 7.]), you want the share of observed values that exceed 3. What is that share?Show answerHide answer
Save this lesson to see this answer.
Question 5 of 10
(2, 3). What shape results from np.stack([a, b], axis=1)?Show answerHide answer
Save this lesson to see this answer.
Question 6 of 10
a = np.array([3, 6]), you need values [3.5, 6.5]. Why does a = a + 0.5 work while a += 0.5 raises an error?Show answerHide answer
Save this lesson to see this answer.
Question 7 of 10
X = np.array([[2., 6., 10.], [4., 8., 12.]]) is centered separately within each row. What result should the correct expression produce?Show answerHide answer
Save this lesson to see this answer.
Question 8 of 10
X = np.array([[3., 9.], [5., 7.], [8., 4.]]) holds two readings. Center each row, then weight the first column by 0.25 and the second by 0.75 and add within each row. What results?Show answerHide answer
Save this lesson to see this answer.
Question 9 of 10
x = np.array([7, 12, 12, 4]), what is x.argmax()?Show answerHide answer
Save this lesson to see this answer.
Question 10 of 10
[group, reading] in D are [[1., 4.], [1., np.nan], [2., 8.], [2., 10.], [2., np.nan]]. Fill each missing reading with its own group's observed mean. What is the mean of all five filled readings?Show answerHide answer
Save this lesson to see this answer.
Stuck on your own question? Homework Help
Key Terms
A
Aggregation
table.mean(axis=0) combines records to give one mean for each measurement column.Aliasing
b = a, the expression b is a is true, and assigning through either name changes that one array.Argmax
[3, 8, 8, 2], argmax returns 1, which is a position rather than the maximum value 8.Argsort
names[np.argsort(scores)] to list names in score order without losing the name-score pairing.Array creation function
np.full((3, 2), 8) creates three rows of two values without requiring six separately written inputs.Axis
data[:, 0] keeps all positions on the row axis and takes its first column.B
Binary ufunc
np.maximum(observed, minimum) chooses the greater of two aligned values at every output position.Boolean indexing
data[data[:, 0] > 10] retains whole rows based on the condition applied to their first column.Boolean mask
t > 25 marks the days whose recorded temperature exceeds 25 °C.Broadcasting
(3,) vector to a shape (8, 3) table applies that vector to each of the eight rows.C
Ceiling
np.ceil applies this upward rounding to array values.np.ceil gives −2.0, whereas for 2.3 it gives 3.0.Centering
X - X.mean(axis=0) subtracts each column's mean from the values in that same column.Clipping
np.clip(readings, 10, 30) retains interior values and replaces readings outside that range with 10 or 30.Column stacking
np.column_stack to create one two-measurement record per person.Compatible dimensions
(5, 1) and (4,) combine into (5, 4) because their aligned axes satisfy the compatibility rule.Complete row
~np.isnan(data).any(axis=1) creates one true entry for each complete record in a numerical table.Concatenation
(2, 4) and (5, 4) along axis 0 makes a seven-row table with four columns.Conditional selection
np.where builds a result by choosing one input at true positions and another at false positions.np.where(x < 0, 0, x) replaces negative values with zero in a new result of the same overall selection shape.Conditional summary
mass[batch == 'B'].mean() averages only masses whose matching batch label is B.Copy
saved = data[:3].copy() preserves an independent subset for later edits or comparisons.Cumulative sum
np.cumsum([2, 5, 1]) gives [2, 7, 8], useful for tracking a balance as entries accumulate.D
Degrees-of-freedom adjustment
ddof.ddof=1, NumPy divides the squared-deviation total by four.dtype
data.dtype can reveal that a stray text label caused numerical-looking values to be stored as strings.E
Element-wise arithmetic
(2, 3) arrays with * gives six paired products in another (2, 3) array.Element-wise logical operation
&, |, or ~ for and, or, or negation.(x >= 2) & (x <= 8) retains values meeting both bounds, with each comparison in parentheses.F
Fancy indexing
a[[4, 1, 4]] includes position 4 twice and preserves the requested output order.First-hit time
Flattening
flatten copies the data, while ravel can share the original data.table.flatten() when you need a separate 1-D result whose edits cannot change the table.Floating-point number
np.allclose when tiny representation differences should be tolerated.Floor
np.floor applies this downward rounding to each input value.np.floor gives −3.0 because −2 would lie above the original negative value.Function domain
np.sqrt(-4.0) normally warns and returns NaN.G
Generator
default_rng and reused through methods that advance its internal state.rng.integers twice continues the stream; recreating rng with the same seed restarts it.H
Homogeneous storage
np.array([2, 3.5]), the integer input becomes a float so both elements share floating-point storage.I
Identity array
np.eye.np.eye(4) creates four diagonal ones in a 4-by-4 array, with zeros in the remaining positions.In-place operation
+= to an integer array fails, while an ordinary addition can create floating-point storage.Index
Indexed assignment
data[:2, 0] = 0 replaces the first-column values in the first two rows of the table.Infinity
inf or -inf and detected as nonfinite.inf with a warning under default NumPy settings.Integer overflow
uint8 arrays containing 250 and 10 wraps to 4 because that dtype cannot hold 260.Integer selector
(8, 3), data[:, 1] returns shape (8,) after removing the column axis.L
Linear spacing
linspace creates this grid from its endpoints and point count.M
Mean filling
Median
[1, 3, 6, 100] is 4.5 even though the unusually large final value raises the mean sharply.Memory sharing
np.shares_memory tests whether two particular arrays overlap.Missing-value code
N
NaN
[4.0, np.nan, 8.0] require floating-point storage, and np.isnan identifies the missing position.NaN-aware aggregation
nanmean or nanmedian.np.nanmean([5., np.nan, 9.]) returns 7.0 by averaging the two observed values.ndarray
(50, 3).Normal distribution
rng.normal.loc=100 and scale=4 uses distribution mean 100 and standard deviation 4, not variance 4.P
Paired coordinates
m[[0, 2], [1, 3]] selects coordinates (0, 1) and (2, 3), not a 2-by-2 block.Percentile
Permutation
rng.permutation(n) into disjoint index slices to assign every record to exactly one subset.Pseudorandom sequence
Q
Quantile
np.quantile(x, 0.75) requests the same position as np.percentile(x, 75) with matching options.R
Random walk
cumsum(axis=1) creates separate walk positions along each trial row.Reduction axis
keepdims.(6, 4) leaves shape (6,), with one result per original row.Reshape
(4, 3) when one row should hold each quarter's three months.Row-major order
[0, 1, 2, 3, 4, 5] to (2, 3) puts [0, 1, 2] in the first row.S
Sampling with replacement
rng.choice.Seed
np.random.default_rng(17) at the start gives a repeatable starting point for the analysis.Shape
(2, 6) describes two rows of six values, while shape (12,) describes one vector of twelve values.Simulation
Singleton axis
[:, None] to a length-four vector creates shape (4, 1), suitable for one value per table row.Size
(4, 7) has size 28 even though its ndim attribute reports only two axes.Slice
a[2:7:2] selects positions 2, 4, and 6, skipping one position between selected values.Splitting
array_split allows unequal part lengths.np.arange(9) at [2, 6] gives parts of lengths 2, 4, and 3 because the numbers are boundaries.Stacking
(3, 5), with one input vector per row.Standard deviation
std() use divisor N by default; ddof=1 selects the sample formula.Standard error
Standardization
(X - X.mean(axis=0)) / X.std(axis=0) standardizes columns that have nonzero standard deviations.Step size
np.arange.np.arange(2, 15, 4) uses a step size of 4 to create the sequence [2 6 10 14].T
Transpose
(2, 5) table gives shape (5, 2), with each old column becoming a row.Trial
Truncation
astype(int) gives −7; applying floor instead would give −8.Type conversion
astype returns a converted copy, and some conversions discard information.np.array([2.7, 5.1]).astype(int) converts the values to 2 and 5 without rounding to nearest.U
Unary ufunc
np.abs on a vector of signed errors produces a vector containing their magnitudes.Uninitialized array
np.empty(100) only when subsequent code will fill every entry before any calculation uses it.Unique values
np.unique returns them sorted and can also return their matching occurrence counts.Universal function
np.sqrt(distances_squared) calculates a square root at every position without using Python's scalar math.sqrt.V
Vectorization
price * quantity calculates every line total without a separate Python loop over items.View
b = a[1:4], setting b[0] = 50 changes a[1] because the basic slice shares data.W
Weighted total
(scores * weights).sum(axis=1) creates a weighted result for every row when weights align with columns.About this lesson
Make your own Study Materials
Turn your notes, slides and documents into Study Guides, Practice Questions, Flashcards and 6 more tools.