Ten questions at a time, drawn from 130. Every answer is explained. Nothing is saved and no account is needed.
If you have a 2D array 'arr' with shape (3, 4), what happens when you perform 'arr + 10'?
Practice quiz for NumPy. Scores are not saved.
If you have a 2D array 'arr' with shape (3, 4), what happens when you perform 'arr + 10'?
Answer: It adds 10 to every element in the array via broadcasting. Broadcasting allows scalars to be applied to every element in an array. The other options are incorrect because NumPy supports scalar-array arithmetic, and it applies to the entire structure, not just specific rows or appending.
From lesson: Introduction to NumPy and ndarray
Which of the following describes the memory behavior of a basic NumPy slice, such as 'sub_arr = arr[0:2]'?
Answer: It creates a view that points to the same underlying data buffer as the original array. NumPy slices are views, meaning they share the same memory. Option 1 is wrong because it requires .copy(), and options 3 and 4 are incorrect as slicing is a fundamental NumPy feature.
From lesson: Introduction to NumPy and ndarray
An array is created with 'np.array([1, 2, 3], dtype=float)'. What is the result of attempting to assign the string 'four' to the first element?
Answer: It will raise a ValueError or TypeError. ndarrays are homogeneous and strictly typed. Since the array is float, it cannot store non-numeric strings, resulting in an error. Options 1, 2, and 4 are incorrect as they ignore the strict data type constraint.
From lesson: Introduction to NumPy and ndarray
What is the result of applying 'np.sum(arr, axis=0)' on a (2, 3) matrix?
Answer: A 1D array of length 3 containing column sums. Axis 0 operation collapses rows, resulting in a sum for each column. Option 1 is for sum() without axis, option 2 is for axis 1, and option 4 describes a scalar broadcast, not an aggregation.
From lesson: Introduction to NumPy and ndarray
Why is 'ndarray' generally faster than a Python list for numerical computations?
Answer: Because ndarrays are written in highly optimized C code and use contiguous memory blocks. Contiguous memory and C-level optimizations make ndarrays fast. Python lists are dynamic collections of pointers. Options 2, 3, and 4 are factually incorrect or irrelevant to the performance difference.
From lesson: Introduction to NumPy and ndarray
If you need an array with 10 elements starting at 0 and ending exactly at 1, which function is the most appropriate?
Answer: np.linspace(0, 1, 10). np.linspace(0, 1, 10) generates 10 evenly spaced values including both 0 and 1. np.arange would fail to include 1 and requires a step size, while ones and zeros do not produce the requested range.
From lesson: Creating Arrays — array, zeros, ones, arange, linspace
What is the result of np.zeros(3, dtype=int)?
Answer: An array of three zeros of type integer. For a 1D array, a single integer is accepted for the shape parameter. By setting dtype=int, the array stores integers instead of the default floats. The other options are incorrect because the shape is valid and the values remain zero.
From lesson: Creating Arrays — array, zeros, ones, arange, linspace
Which of the following expressions creates a 2x3 matrix of ones?
Answer: np.ones((2, 3)). np.ones requires the shape to be passed as a single tuple argument. np.ones(2, 3) is wrong because it interprets the second argument as the 'dtype'. np.array syntax in option 4 is invalid.
From lesson: Creating Arrays — array, zeros, ones, arange, linspace
What does np.arange(2, 10, 3) return?
Answer: array([2, 5, 8]). np.arange(start, stop, step) starts at 2, increments by 3 until it reaches 10 (exclusive). 2, 5, 8 are generated; the next would be 11, which exceeds the limit. The other options either use the wrong step or miscalculate the stop boundary.
From lesson: Creating Arrays — array, zeros, ones, arange, linspace
Why might you choose np.linspace(0, 10, 5) over np.arange(0, 10, 2)?
Answer: To ensure the final value 10 is always included. linspace guarantees the inclusion of the endpoint (10) and determines the number of samples, whereas arange relies on a step size that may not reach the endpoint exactly. The other options do not accurately describe the functional difference.
From lesson: Creating Arrays — array, zeros, ones, arange, linspace
An array is created with the shape (3, 4). What will calling .size return?
Answer: 12. .size returns the total number of elements, which is the product of the shape dimensions (3 * 4 = 12). The other options represent individual dimensions, their sum, or are incorrect calculations.
From lesson: Array Attributes — shape, dtype, ndim, size
If an array has .ndim equal to 2, which of the following is true regarding its .shape?
Answer: The shape tuple will contain exactly two integers.. .ndim represents the number of dimensions. A 2D array must have a shape tuple with exactly two values (rows, columns). A 1D array has 1 value, and 3D has 3.
From lesson: Array Attributes — shape, dtype, ndim, size
What is the primary purpose of the .dtype attribute?
Answer: To describe the type of elements stored in the array.. .dtype specifies the data type of the elements (e.g., int32, float64). The other attributes deal with structure, memory, or storage order, not the element type.
From lesson: Array Attributes — shape, dtype, ndim, size
Consider an array 'arr' defined as np.array([10, 20, 30]). What is the result of arr.ndim?
Answer: 1. A 1D array (vector) has exactly 1 axis, so .ndim is 1. .size would be 3, and 0 would imply a scalar, while 30 is the content of the last element.
From lesson: Array Attributes — shape, dtype, ndim, size
How does .shape change when you transpose a (2, 5) array?
Answer: It becomes (5, 2).. Transposing an array swaps its dimensions. A shape of (rows, columns) becomes (columns, rows), thus (2, 5) becomes (5, 2). The other options ignore the logic of transposition.
From lesson: Array Attributes — shape, dtype, ndim, size
If you perform 'view = arr[0:2]', and then modify 'view[0] = 99', what happens to the original 'arr'?
Answer: The original array is modified because slicing creates a view.. Slicing in NumPy creates a view, meaning both variables point to the same memory. Thus, modification affects the original. Option 0 is wrong because slicing doesn't copy; Option 2 is wrong as views are mutable; Option 3 is wrong as no duplication occurs.
From lesson: Array Indexing and Slicing
What is the shape of the result if you extract a single row from a 2D array using 'arr[0, :]' compared to 'arr[0:1, :]'?
Answer: The first returns a 1D array, the second returns a 2D array.. Integer indexing reduces dimensions (dropping the axis), while slicing preserves dimensions. Option 0 is wrong because slicing maintains rank. Option 1 is wrong because integer indexing reduces rank. Option 3 reverses the correct behavior.
From lesson: Array Indexing and Slicing
What does the expression 'arr[::-1]' achieve when applied to a NumPy array?
Answer: It returns a view of the array with elements in reverse order.. The step parameter -1 traverses the array backwards. Option 0 is wrong as negative steps are valid. Option 1 is wrong because it only reverses order, not sorts by value. Option 3 is wrong as it does not modify the structure.
From lesson: Array Indexing and Slicing
Given a 2D array 'arr', what does 'arr[[0, 1], [0, 1]]' return?
Answer: The elements at positions (0,0) and (1,1) as a 1D array.. This is fancy indexing; it maps pairs of indices (0,0) and (1,1). Option 0 is wrong because slicing would be required for a subarray. Option 2 describes the result. Option 3 is wrong as fancy indexing is a standard NumPy feature.
From lesson: Array Indexing and Slicing
If you have a 3D array of shape (4, 4, 4), what does the slice 'arr[:, :, 0]' return?
Answer: A 2D array of shape (4, 4).. Slicing the first two dimensions fully and selecting index 0 in the third dimension reduces the rank to 2. Option 1 is wrong because integer indexing removes the dimension. Option 2 is wrong as the shape is (4,4). Option 3 is wrong as two full dimensions remain.
From lesson: Array Indexing and Slicing
What is the primary difference in how NumPy handles the bitwise '&' operator compared to the Python 'and' keyword when applied to boolean arrays?
Answer: The '&' operator performs element-wise operations, whereas 'and' evaluates the truth value of the entire array object.. The bitwise operator '&' is overloaded in NumPy to perform element-wise AND logic. The Python keyword 'and' is used for boolean logic between single objects and will raise a ValueError when used on non-empty arrays, or evaluate the truthiness of the whole structure, which is not what is intended for masking.
From lesson: Boolean Masking and Fancy Indexing
If you have an array 'arr' and perform 'result = arr[[0, 2, 4]]', what is the nature of the returned object 'result'?
Answer: A copy of the original array, meaning changes to 'result' do not affect 'arr'.. Fancy indexing (using a list of indices) always returns a copy of the data. Changes to this result do not propagate back to the original array, unlike slices which return views.
From lesson: Boolean Masking and Fancy Indexing
Given a 2D array 'data' of shape (5, 5), what does 'data[data > 10] = 0' do?
Answer: It sets all elements in the array that meet the condition to 0, maintaining the original (5, 5) shape.. Boolean masking with an assignment operation modifies the original array in-place. The mask selects only the elements satisfying the condition; the structural integrity (shape) of the array is preserved.
From lesson: Boolean Masking and Fancy Indexing
If 'arr' is a 1D array, what is the output shape of 'arr[arr > 5]' if 3 elements satisfy the condition?
Answer: (3,). Boolean indexing always flattens the result into a 1D array containing only the elements where the mask is True. Here, it will be a 1D array of length 3.
From lesson: Boolean Masking and Fancy Indexing
To select elements from a 2D array using fancy indexing to get specific coordinates (e.g., (0,0) and (1,2)), what is the correct syntax?
Answer: arr[[0, 1], [0, 2]]. Passing a list of row indices and a list of column indices allows you to pick out specific coordinates. Option 0 correctly pairs 0 with 0 and 1 with 2. Other options are syntax errors or perform different slicing operations.
From lesson: Boolean Masking and Fancy Indexing
What is the result of adding two 1D NumPy arrays of different lengths using the '+' operator?
Answer: The operation fails and raises a ValueError. Option 2 is correct because element-wise operations require compatible shapes; NumPy cannot guess how to match them. Option 1 describes a different operation (like a custom pad), not default behavior. Option 3 and 4 are incorrect because NumPy refuses to lose data or assume alignment without explicit broadcasting rules.
From lesson: Element-wise Arithmetic
Given a = np.array([1, 2, 3]) and b = 2, what is the result of a * b?
Answer: [2, 4, 6]. Option 3 is correct because NumPy uses broadcasting to apply the scalar 2 to every element in array 'a'. Option 1 is incorrect as NumPy returns an array, not a scalar. Option 2 is incorrect because '*' on a list would repeat it, but in NumPy, it performs multiplication. Option 4 is incorrect because scalars are broadcastable to any shape.
From lesson: Element-wise Arithmetic
Which of the following describes the behavior of np.add(a, b) compared to a + b?
Answer: They are functionally identical for standard ndarrays. Option 2 is correct because the '+' operator is overloaded to call the underlying np.add() ufunc. Option 1 is false as there is no performance difference. Option 3 is incorrect because the 'out' parameter is optional. Option 4 is false as both handle multidimensional arrays identically.
From lesson: Element-wise Arithmetic
If array A has shape (3, 1) and array B has shape (1, 3), what is the shape of A + B?
Answer: (3, 3). Option 1 is correct due to broadcasting rules: dimensions of size 1 are stretched to match the larger dimension. Option 2 and 3 are incorrect shapes. Option 4 is incorrect because the arrays are fully compatible under broadcasting rules.
From lesson: Element-wise Arithmetic
What is the outcome of performing division on an array containing a zero?
Answer: The operation succeeds, resulting in 'inf' or 'nan' values in the result. Option 3 is correct because NumPy handles floating-point division by zero by issuing a warning and producing 'inf' or 'nan'. Option 1 is incorrect because it is a warning, not a hard crash. Option 2 and 4 are incorrect as they do not reflect the standard IEEE 754 handling used by NumPy.
From lesson: Element-wise Arithmetic
Which of the following array shapes can be added together without an error?
Answer: (4, 1) and (1, 4). Option 1 is correct because trailing dimensions are 4 and 1, and the leading dimensions are 1 and 4, which are compatible via broadcasting. Option 0 fails because 5 != 3. Option 2 fails because neither dimension is 1. Option 3 fails because the trailing dimension 2 is not equal to 5 and neither is 1.
From lesson: Broadcasting Rules
If you have an array A of shape (10, 5) and array B of shape (5,), what is the result of A + B?
Answer: An array of shape (10, 5). Correct. NumPy aligns (10, 5) and (5,) by prepending 1s to the smaller array to make it (1, 5). The 1 broadcasts against the 10, resulting in (10, 5). Others are wrong as they violate shape matching rules.
From lesson: Broadcasting Rules
How does NumPy resolve broadcasting for dimensions that do not match?
Answer: It requires that one of the dimensions in the pair is exactly 1.. NumPy requires that for every dimension, they are equal or one is 1. Stretching or multiples don't satisfy the strict mathematical requirements of broadcasting.
From lesson: Broadcasting Rules
Given array X with shape (3, 1) and Y with shape (1, 3), what is the shape of X + Y?
Answer: (3, 3). The trailing dimensions are 1 and 3 (compatible), and the leading dimensions are 3 and 1 (compatible). The resulting shape takes the maximum of each dimension: (max(3,1), max(1,3)) which is (3, 3).
From lesson: Broadcasting Rules
What is the purpose of using np.newaxis in a broadcasting operation?
Answer: To increase the rank of an array by inserting a new axis of size 1.. np.newaxis increases the dimension count, allowing you to explicitly position the '1' in the shape, which is essential for forcing broadcasting in specific alignments. It does not flatten, delete, or change data types.
From lesson: Broadcasting Rules
What is the primary advantage of using a NumPy universal function (ufunc) over a standard Python for-loop when performing element-wise operations?
Answer: Ufuncs perform operations in pre-compiled C loops, avoiding Python overhead. Ufuncs are implemented in C, allowing them to execute operations in bulk at near-machine speeds. Option 0 is false as ufuncs don't plot, 2 is false as intermediate arrays may increase memory usage, and 3 is false as they are not inherently recursive.
From lesson: Universal Functions (ufuncs)
When calling a ufunc with the 'out' argument, what happens to the output array?
Answer: The result is stored directly in the provided array, overwriting its previous contents. The 'out' parameter specifies an existing array to hold the calculation result. Option 0 is wrong because no new array is allocated. Option 1 is wrong because it stores it in 'out', not the input. Option 3 is a misunderstanding of the parameter's purpose.
From lesson: Universal Functions (ufuncs)
What happens when you apply a ufunc to two arrays with different shapes?
Answer: NumPy broadcasts the arrays to a compatible shape if possible. Broadcasting is a core feature of ufuncs that allows them to handle inputs of different shapes if they are dimensionally compatible. Options 0, 2, and 3 are incorrect as they do not describe the standard NumPy broadcasting behavior.
From lesson: Universal Functions (ufuncs)
Which of the following describes the 'where' parameter in a ufunc?
Answer: It accepts a boolean array to specify which elements should be processed. The 'where' parameter acts as a mask, limiting the operation to specific indices. Option 0 confuses this with memory addresses, 2 is for I/O, and 3 describes the 'axis' parameter.
From lesson: Universal Functions (ufuncs)
If you want to perform a cumulative sum (not element-wise) across an array, why would you use 'ufunc.accumulate' instead of a standard ufunc?
Answer: Because 'accumulate' calculates results based on previous values, which is not an element-wise operation. Standard ufuncs apply operations to independent elements, whereas 'accumulate' tracks state, making it a reduction-related operation. Option 0 is false, 1 is arbitrary, and 3 is incorrect as this isn't the purpose of accumulation.
From lesson: Universal Functions (ufuncs)
Given an array 'arr' of shape (3, 4), what happens if you call 'arr.mean(axis=0)'?
Answer: It returns an array of shape (4,), representing the mean of each column.. Axis=0 operates down the rows, collapsing them into a single summary per column. Option 0 describes the default behavior with no axis; option 2 describes axis=1; option 3 is incorrect as aggregation functions handle non-square arrays perfectly.
From lesson: Aggregation — sum, mean, min, max, std
If you need to find the standard deviation of a dataset representing a sample (not a population), which parameter is required?
Answer: ddof=1. ddof (Delta Degrees of Freedom) must be set to 1 to divide by N-1 instead of N. Axis controls direction, keepdims preserves dimensions, and dtype changes the precision of calculation, none of which affect the population/sample correction.
From lesson: Aggregation — sum, mean, min, max, std
Which function is best to use when you want to compute the sum of an array while ignoring any missing (NaN) values?
Answer: np.nansum(arr). np.nansum is the standard NumPy function designed to treat NaNs as zero. The other options are incorrect function names or parameters that do not exist in the NumPy library.
From lesson: Aggregation — sum, mean, min, max, std
When computing 'arr.max(axis=1, keepdims=True)' on a (5, 3) array, what is the resulting shape?
Answer: (5, 1). keepdims=True prevents the reduced axis from disappearing, maintaining it as a size of 1. Since we collapsed axis 1 (the columns), the result becomes (5, 1). Option 0 is the result without keepdims; others are incorrect shapes.
From lesson: Aggregation — sum, mean, min, max, std
What is the result of calling 'min()' on a boolean array in NumPy?
Answer: The minimum value of the underlying integers (0 for False, 1 for True).. NumPy treats True as 1 and False as 0. Therefore, the minimum of a boolean array is 0 if at least one False exists, and 1 if all elements are True. The other options describe incorrect or non-existent behaviors.
From lesson: Aggregation — sum, mean, min, max, std
What is the correct way to filter an array 'arr' for elements that are both greater than 5 and less than 10?
Answer: arr[(arr > 5) & (arr < 10)]. Bitwise operators require parentheses due to operator precedence, which is why option 3 is correct. Option 1 fails because 'and' is for scalars. Option 2 fails due to precedence issues. Option 4 uses a non-existent function name.
From lesson: Comparison and Logical Operations
Given 'a = np.array([1, 2, 3])' and 'b = np.array([1, 2, 4])', what does 'a == b' return?
Answer: array([True, True, False]). NumPy comparison operators perform element-wise evaluation. '1==1' is True, '2==2' is True, and '3==4' is False, resulting in an array of booleans. Options 1 and 2 are incorrect because they expect a scalar output, and option 4 is logically wrong.
From lesson: Comparison and Logical Operations
Which method is the most appropriate to check if any element in a boolean array is True?
Answer: arr.any(). The .any() method returns True if at least one element is True. .all() requires all elements to be True. 'if arr' and 'bool(arr)' raise a ValueError because NumPy does not know if you mean the whole array or specific elements.
From lesson: Comparison and Logical Operations
What is the result of 'np.where(arr > 0, arr, 0)'?
Answer: An array with values from 'arr' where they are positive, and 0 otherwise.. np.where(condition, x, y) returns elements from x where the condition is True, and from y otherwise. Option 1 describes this exact behavior. Other options describe different functions like np.argwhere or boolean indexing.
From lesson: Comparison and Logical Operations
Why does 'a = np.array([np.nan]); a == np.nan' return '[False]'?
Answer: Because NaN is defined as not equal to any value, including itself.. Floating-point standards define NaN (Not a Number) as unequal to every value, which is why a equality check fails. Option 1 is irrelevant to the logic, option 2 is false, and while precision matters in some cases, it is not the reason for this specific standard behavior.
From lesson: Comparison and Logical Operations
You have a 1D array of shape (12,). Which operation effectively transforms it into a 3x4 matrix?
Answer: arr.reshape(3, 4). reshape(3, 4) creates a new view with the requested dimensions. Transpose only swaps existing axes, resize is for in-place modification without returning a new view, and swapaxes expects axis indices, not new dimensions.
From lesson: Reshaping and Transposing
What is the result of using -1 in a reshape command: arr.reshape(-1, 2)?
Answer: It automatically calculates the first dimension based on the total array size and the specified second dimension.. -1 tells NumPy to infer the size of that dimension based on the remaining elements. The other options are incorrect as NumPy is designed to handle this inference for convenience, and -1 is a valid placeholder, not an error.
From lesson: Reshaping and Transposing
If 'a' is a 3D array of shape (2, 3, 4), what is the shape of 'a.T'?
Answer: (4, 3, 2). The .T attribute reverses the order of dimensions for an array. For (2, 3, 4), reversing yields (4, 3, 2). The other options represent incorrect permutations.
From lesson: Reshaping and Transposing
Which method is specifically used to swap two axes of an array?
Answer: swapaxes(). swapaxes() is designed to interchange two specified axes. reshape and ravel change the shape/dimensionality, while flatten returns a copy of the array collapsed into one dimension.
From lesson: Reshaping and Transposing
How does ravel() differ from flatten()?
Answer: ravel() returns a view whenever possible, while flatten() always returns a copy.. ravel() returns a view of the original array if possible, making it more memory-efficient. flatten() guarantees a new copy. The other statements incorrectly describe their return types or dimensionality constraints.
From lesson: Reshaping and Transposing
You have two 1D arrays of shape (3,). Which function call will result in an array of shape (2, 3)?
Answer: np.vstack([a, b]). vstack stacks rows vertically, turning two (3,) arrays into a (2, 3) matrix. hstack and concatenate on 1D arrays would result in shape (6,). stack with axis=1 would produce (3, 2).
From lesson: Stacking — vstack, hstack, concatenate
What is the primary difference between np.concatenate and np.stack?
Answer: stack adds a new dimension to the output, whereas concatenate joins along an existing axis. stack creates a new axis (e.g., stacking two 2D arrays creates a 3D array), while concatenate joins along an existing axis without changing the rank of the arrays.
From lesson: Stacking — vstack, hstack, concatenate
Given two arrays 'a' and 'b' of shape (4, 4), what is the shape of the result of np.hstack([a, b])?
Answer: (4, 8). hstack stacks arrays horizontally (along the second axis), doubling the number of columns. Thus, (4, 4) + (4, 4) becomes (4, 8). (8, 4) is vstack, and the others represent different stacking behaviors.
From lesson: Stacking — vstack, hstack, concatenate
If you have two arrays of shape (3, 2) and (3, 4), which operation is valid?
Answer: np.hstack([a, b]). hstack works because the number of rows (dimension 0) matches (3 and 3). vstack requires matching column counts (2 and 4), and concatenate requires matching dimensions along the chosen axis, which is not true here for axis=1.
From lesson: Stacking — vstack, hstack, concatenate
How do you join a list of ten (2, 2) arrays into a single (10, 2, 2) array?
Answer: np.stack(list_of_arrays, axis=0). np.stack adds a new dimension at the specified axis. By default (axis=0), it places the ten arrays along the first dimension to create a (10, 2, 2) structure. The others would either attempt to join along existing axes or flatten the result.
From lesson: Stacking — vstack, hstack, concatenate
If you have a 1D array of length 10 and call np.array_split(arr, 3), what will be the shape of the sub-arrays?
Answer: Three arrays of length 4, 3, and 3. array_split handles non-divisible lengths by distributing the extra elements to the first sub-arrays. Option 1 is wrong because it puts the extra on the end, and Option 3 is wrong because array_split is designed to handle this case.
From lesson: Splitting Arrays
What is the primary difference between np.split and np.array_split when a split does not result in equal parts?
Answer: np.split raises a ValueError, while np.array_split creates unequal chunks. np.split strictly requires the array to be divisible by the integer provided, whereas np.array_split allows for unequal segments, preventing the ValueError.
From lesson: Splitting Arrays
Given a 2D array of shape (4, 4), what happens if you run np.hsplit(arr, 2)?
Answer: It splits the array into two (4, 2) arrays along columns. hsplit performs horizontal splitting, which acts on columns (axis 1). A 4x4 array split into 2 horizontal parts results in two 4x2 arrays. Row splitting is done via vsplit.
From lesson: Splitting Arrays
You want to split an array at specific indices [2, 5]. Which function is appropriate to use?
Answer: np.array_split(arr, [2, 5]). Passing a list of integers to split or array_split tells NumPy to slice the array at those specific indices. Other options either use integers (dividing into equal parts) or specific axis-based splitting.
From lesson: Splitting Arrays
What is the result of splitting an array using an index that is exactly equal to the array length?
Answer: An empty array at the end. Splitting at the array length results in the full array being placed in the first segment and an empty array in the second segment, as indices are treated as boundaries.
From lesson: Splitting Arrays
If you have a 3x3 array 'arr' and you execute 'b = arr.flatten()', what is the result of 'b[0] = 99'?
Answer: The original 'arr' remains unchanged.. flatten() returns a copy of the array. Modifying the copy does not affect the original. Option 0 describes a view behavior (like ravel), Option 2 is incorrect because NumPy arrays are mutable, and Option 3 makes no sense.
From lesson: Flattening and Raveling
Which of the following scenarios describes the primary benefit of using ravel() over flatten()?
Answer: ravel() avoids memory copying whenever the array's memory layout allows.. ravel() is preferred for performance because it returns a view of the original array if the data is contiguous, whereas flatten() always creates a copy. The other options are either false or not the primary benefit.
From lesson: Flattening and Raveling
Given a 2x2 array created via 'np.arange(4).reshape(2, 2).T', why does calling .ravel() behave differently than on a standard array?
Answer: It produces a copy because the transposed array is not C-contiguous.. Transposing an array breaks C-contiguity. Since ravel() tries to return a view, but cannot do so on non-contiguous memory, it must create a copy. The other answers do not accurately describe NumPy's memory management.
From lesson: Flattening and Raveling
How does setting 'order="F"' in the ravel() function change the output for a 2x2 matrix [[1, 2], [3, 4]]?
Answer: The output becomes [1, 3, 2, 4].. 'F' stands for Fortran order, which traverses the array column by column. Reading the columns of [[1, 2], [3, 4]] gives 1, 3, then 2, 4. 'C' order would yield [1, 2, 3, 4].
From lesson: Flattening and Raveling
You have a 4D array and want to convert it into a 1D array while ensuring you do not consume extra memory. Which approach is most robust?
Answer: arr.ravel(). ravel() is the specific tool for flattening while prioritizing a view over a copy. flatten() always copies, reshape() may fail on non-contiguous memory without explicit handling, and concatenate is inefficient for dimensionality reduction.
From lesson: Flattening and Raveling
Given an array 'a = np.array([1, 10, 100])', what is the result of np.log10(a)?
Answer: [0, 1, 2]. np.log10 computes the base-10 logarithm. log10(1)=0, log10(10)=1, and log10(100)=2. The other options represent natural logs, the original array, or incorrect scalar applications.
From lesson: Mathematical Functions — sqrt, exp, log
What is the primary difference between np.exp(x) and np.power(e, x) where e is np.e?
Answer: np.exp is specifically optimized for efficiency and precision with base e. np.exp is a specialized universal function optimized for floating-point calculations with the mathematical constant e. While np.power(np.e, x) yields the same result, np.exp is faster and handles floating-point errors more gracefully.
From lesson: Mathematical Functions — sqrt, exp, log
If you need to calculate ln(1 + x) for very small values of x, why is np.log1p(x) preferred over np.log(1 + x)?
Answer: It avoids precision loss due to floating-point arithmetic when x is near 0. When x is tiny, 1+x rounded to floating point precision loses the information about x. np.log1p(x) uses a specific Taylor expansion or algorithm to preserve the precision of x, whereas np.log(1+x) may return 0 erroneously.
From lesson: Mathematical Functions — sqrt, exp, log
What happens when you execute np.sqrt(np.array([-1, 0, 1]))?
Answer: It returns [nan, 0, 1] with a runtime warning. NumPy produces a RuntimeWarning for the square root of a negative number and returns 'nan' (Not a Number) for that specific index. It does not crash the program (error) nor does it silently ignore or change the input value.
From lesson: Mathematical Functions — sqrt, exp, log
You have an array x. Which operation correctly computes the value of e^(x^2)?
Answer: np.exp(x**2). The expression e^(x^2) requires squaring x first, then passing it to the exponential function. np.exp(x)**2 is equivalent to (e^x)^2 = e^(2x), which is mathematically different.
From lesson: Mathematical Functions — sqrt, exp, log
If A and B are 2D arrays of shape (3, 2) and (2, 3) respectively, what is the shape of the result of A @ B?
Answer: (3, 3). Matrix multiplication (A @ B) results in a matrix with rows from A and columns from B. (3, 2) @ (2, 3) yields (3, 3). Options 1 and 2 are dimensionally impossible, and the shapes match perfectly, so no error occurs.
From lesson: Linear Algebra — dot, matmul, inv, eig
Which function is best suited to find the solution 'x' to the linear system Ax = b in a numerically stable way?
Answer: np.linalg.solve(A, b). np.linalg.solve() uses LU decomposition which is much more numerically stable than computing an explicit inverse. Options 0 and 1 are unstable and prone to floating-point errors, and option 3 uses division which is not defined for matrix-vector systems.
From lesson: Linear Algebra — dot, matmul, inv, eig
Given a square matrix M, what does the 'v' output of 'w, v = np.linalg.eig(M)' represent?
Answer: A matrix where each column is an eigenvector of M. np.linalg.eig returns eigenvalues in array 'w' and eigenvectors as columns in matrix 'v'. Option 0 is np.linalg.inv, option 2 describes a separate operation, and option 3 is M.T.
From lesson: Linear Algebra — dot, matmul, inv, eig
What happens if you use the '*' operator between two 2D NumPy arrays of the same shape?
Answer: Each element of the first matrix is multiplied by the corresponding element of the second. In NumPy, '*' is the element-wise multiplication operator (Hadamard product). It does not perform matrix multiplication (which uses @), nor does it raise an error for identical shapes. It is not equivalent to the dot product.
From lesson: Linear Algebra — dot, matmul, inv, eig
In the context of np.linalg.eig, how are the eigenvalues and eigenvectors related to the matrix A?
Answer: A @ v[:, i] == w[i] * v[:, i]. The definition of an eigenvalue/eigenvector pair (w, v) is Av = λv. In NumPy, this translates to A @ v[:, i] (the transformed vector) being equal to the scalar eigenvalue times the vector itself. The other options involve incorrect mathematical operations like addition or matrix division.
From lesson: Linear Algebra — dot, matmul, inv, eig
Given a square matrix A and vector b, which method is the most numerically stable way to solve Ax = b in NumPy?
Answer: np.linalg.solve(A, b). np.linalg.solve uses LU decomposition, which is faster and more stable than computing the inverse. Option 0 is unstable, option 2 is mathematically invalid, and option 3 performs element-wise multiplication.
From lesson: Solving Linear Systems
What is the expected behavior when calling np.linalg.solve(A, b) if matrix A is singular?
Answer: It raises a LinAlgError.. A singular matrix lacks an inverse, and NumPy is designed to raise a LinAlgError to prevent the propagation of mathematically invalid results. The other options are incorrect as they imply silent failure or incorrect behavior.
From lesson: Solving Linear Systems
You have an overdetermined system (more equations than variables) and want to minimize the squared error. Which function should you use?
Answer: np.linalg.lstsq. np.linalg.lstsq performs a least-squares solution, which is the standard approach for overdetermined systems. np.linalg.solve requires a square, full-rank matrix, and the others do not compute solutions for linear systems.
From lesson: Solving Linear Systems
What does the condition number returned by np.linalg.cond(A) tell you about the system Ax = b?
Answer: The sensitivity of the solution to errors in input data.. The condition number measures how much the output value of the function can change for a small change in the input argument. High values indicate the system is poorly conditioned. It does not measure count, time, or complexity.
From lesson: Solving Linear Systems
If matrix A is (3, 3) and vector b is (3,), what is the shape of the result returned by np.linalg.solve(A, b)?
Answer: (3,). NumPy broadcasting and linear algebra functions typically return a 1D array of shape (N,) when solving for a vector b of shape (N,). Option 0 is a matrix, and the others represent incompatible or different array dimensions.
From lesson: Solving Linear Systems
Given an array 'arr' with shape (3, 4), what is the result of np.var(arr, axis=1)?
Answer: A 1D array of length 3 containing the variance of each row.. axis=1 reduces the array across columns, resulting in a value for each row. Scalar is for default axis=None. Length 4 would be axis=0. Variance is not an element-wise mapping.
From lesson: NumPy for Statistics
If you need to calculate the sample standard deviation (unbiased estimator) of an array, which parameter must be adjusted in np.std()?
Answer: set ddof=1. ddof (delta degrees of freedom) defaults to 0 (population). Setting it to 1 changes the divisor to N-1, providing the sample standard deviation. Axis, dtype, and keepdims do not influence the estimator bias.
From lesson: NumPy for Statistics
What is the primary difference between np.mean() and np.nanmean()?
Answer: np.mean() includes NaN in the count, whereas np.nanmean() ignores it.. np.mean() treats NaNs as arithmetic poisons, returning NaN for the whole operation. np.nanmean() specifically excludes these values during computation. Speed and data types are not the distinguishing factors.
From lesson: NumPy for Statistics
You have a dataset where each column represents a variable. How should you pass this to np.cov() to get the correct covariance matrix?
Answer: Pass the transpose of the array using .T.. np.cov() expects rows to be variables. Since the prompt specifies columns are variables, transposing (.T) is necessary. Flattening loses structure, and passing columns directly treats them as observations, which is wrong.
From lesson: NumPy for Statistics
What does setting keepdims=True do in a statistical reduction function like np.sum() or np.mean()?
Answer: It maintains the original number of dimensions, making the result broadcastable against the input.. keepdims=True ensures the reduced axis remains in the shape as a dimension of size 1, allowing for easy broadcasting back to the original array shape. It does not prevent reduction, nor does it affect type or NaN handling.
From lesson: NumPy for Statistics
Which approach is considered the best practice for thread-safe random number generation in NumPy?
Answer: Instantiate a unique Generator object for each thread. Instantiating a Generator per thread avoids contention and ensures state isolation. Global functions rely on a shared state that is not thread-safe. Re-creating the generator inside a thread function would result in identical sequences if called simultaneously.
From lesson: Random Number Generation
What is the primary difference between np.random.random() and np.random.standard_normal()?
Answer: One follows a uniform distribution and the other follows a normal distribution. np.random.random() provides values from a uniform distribution [0.0, 1.0), whereas standard_normal() produces samples from a normal distribution with mean 0 and variance 1. Both can return arrays, and both are influenced by the global state.
From lesson: Random Number Generation
If you need an array of 1000 integers between 1 and 10 (inclusive), which call is most correct?
Answer: np.random.default_rng().integers(1, 11, 1000). np.random.default_rng().integers() is the modern API. With low=1 and high=11, it is inclusive of 1 and exclusive of 11, correctly covering 1-10. Option 1 uses legacy methods. Option 2 excludes the value 10. Option 3 is deprecated.
From lesson: Random Number Generation
How does using a fixed seed with a Generator instance impact array generation?
Answer: It forces the random sequence to be identical across runs with the same seed. A fixed seed ensures that the underlying bit generator produces the same sequence of bits, resulting in reproducible output. It does not affect CPU usage, memory, or the type of distribution (e.g., normal vs uniform).
From lesson: Random Number Generation
Why should you prefer Generator objects over the legacy np.random.* functions?
Answer: Generators allow for easier serialization of the internal state. Generator objects provide improved statistical properties and allow you to capture/save their state, which is crucial for reproducible simulations. They are not necessarily faster in all cases, they still require shape arguments, and legacy functions remain for backward compatibility.
From lesson: Random Number Generation
You need to generate a 2x3 matrix of floats sampled from a normal distribution with a mean of 0 and a variance of 4. Which code snippet is correct?
Answer: np.random.normal(0, 2, size=(2, 3)). Option 1 is correct because scale is standard deviation, which is the square root of 4 (i.e., 2). Option 0 is wrong because it uses variance instead of standard deviation. Option 2 is wrong because the parameter is 'size', not 'shape'. Option 3 is wrong because it creates a 1D array instead of a 2x3 matrix.
From lesson: Distributions — normal, uniform, binomial
What is the primary difference between np.random.uniform(0, 10, 5) and np.random.randint(0, 10, 5)?
Answer: One generates floats, the other integers.. Option 0 is correct: uniform generates continuous floats, while randint generates discrete integers. Option 1 is incorrect because both functions have specific rules for bounds, but that isn't the primary distinction. Option 2 is wrong as both are types of uniform distributions. Option 3 is wrong as the last argument defines sample count for both.
From lesson: Distributions — normal, uniform, binomial
If you want to simulate flipping a fair coin 10 times, 1000 separate times, which parameters should you pass to np.random.binomial?
Answer: n=10, p=0.5, size=1000. Option 1 represents 10 trials per experiment (n=10) performed 1000 times (size=1000). Option 0 is wrong as it only flips the coin once. Option 2 is wrong because the size should be the number of experiments. Option 3 is wrong as it represents a single experiment with 1000 trials.
From lesson: Distributions — normal, uniform, binomial
How does setting np.random.seed(42) affect subsequent calls to np.random.normal?
Answer: It makes the random stream deterministic and reproducible.. Option 1 is correct: setting the seed initializes the pseudo-random number generator to a specific state, ensuring the same 'random' numbers are produced every time the code runs. Options 0, 2, and 3 are incorrect because the seed only controls the sequence, not the statistical properties or range of the distribution.
From lesson: Distributions — normal, uniform, binomial
You generate data using np.random.uniform(low=0.0, high=1.0, size=1000). What will be the approximate result of calling .mean() on this array?
Answer: 0.5. Option 2 is correct because the mean of a uniform distribution over [0, 1] is (0+1)/2 = 0.5. With a large sample size of 1000, the sample mean will converge to the population mean. Option 0 and 1 are incorrect as they are outside the expected center. Option 3 is incorrect because while the values change, the Law of Large Numbers ensures the mean remains stable near 0.5.
From lesson: Distributions — normal, uniform, binomial
When using np.random.default_rng(seed=42), what happens if you call the generator's random method multiple times in the same script?
Answer: It generates a deterministic sequence of numbers based on the initial seed.. Option 2 is correct; a Generator instance creates a deterministic sequence from a seed. Option 1 is wrong because the internal state updates. Option 3 is wrong because the state persists. Option 4 is wrong because the sequence is reproducible, not independent.
From lesson: Setting Seeds for Reproducibility
If you have two separate code blocks using the same seed with np.random.default_rng(), what is the relationship between the numbers they produce?
Answer: The first number generated in both blocks will be identical.. Option 1 is correct because each generator starts at the same state defined by the seed. Option 2 is incorrect because the sequences are identical from the start. Option 3 is false as seeds control the sequence. Option 4 is incorrect because NumPy's algorithms are designed for cross-platform consistency.
From lesson: Setting Seeds for Reproducibility
Why is the legacy np.random.seed() function considered less ideal for complex simulations compared to np.random.Generator?
Answer: It relies on a global state that can be inadvertently altered by other code.. Option 3 is correct; global state is prone to interference. Option 1 and 4 are false as both systems handle various types, and Option 2 is not the primary reason for the shift to the Generator API.
From lesson: Setting Seeds for Reproducibility
To ensure your results are reproducible across different runs of a NumPy script, where should you place the seed initialization?
Answer: At the very beginning of the main execution block.. Option 2 is correct because placing it early ensures all subsequent operations use the same predictable state. Placing it later (Option 1 and 3) risks accidental state consumption, and Option 4 is false as timing and order are critical.
From lesson: Setting Seeds for Reproducibility
If you pass an existing Generator instance to a function that requires a seed, what is the best practice for reproducibility?
Answer: Pass the generator instance directly to ensure state continuity.. Option 2 is correct as it preserves the state. Option 1 is ineffective because re-seeding resets the state. Option 3 is incorrect as it creates a duplicate sequence. Option 4 would lead to non-reproducible results.
From lesson: Setting Seeds for Reproducibility
Why does a NumPy array generally provide faster computation than a Python list for numerical tasks?
Answer: NumPy arrays are stored in contiguous memory blocks, allowing for CPU cache optimization.. NumPy arrays are stored in contiguous memory, which significantly improves cache locality compared to Python lists, which are arrays of pointers. Option 0 is false as parallelization requires specific routines; option 2 is false as NumPy is statically typed; option 3 is false as arrays are typically larger due to strict data types.
From lesson: NumPy vs Python Lists — Speed Comparison
Which of the following scenarios best demonstrates the 'vectorization' performance advantage of NumPy?
Answer: Calculating the square root of every element in an array using np.sqrt().. Vectorization via np.sqrt() pushes the loop into compiled C code, bypassing Python overhead. Options 0 and 1 force Python-level iteration, which is slow. Option 3 is an anti-pattern that causes frequent re-allocations.
From lesson: NumPy vs Python Lists — Speed Comparison
What is the primary reason for avoiding the use of Python's 'append' equivalent for NumPy arrays during a loop?
Answer: It forces a full re-allocation and memory copy of the array every time an element is added.. NumPy arrays are fixed-size; np.append() returns a brand new array after copying all existing data, leading to quadratic time complexity. The other options either describe different behaviors or are not the primary cause of the performance degradation.
From lesson: NumPy vs Python Lists — Speed Comparison
In a performance-critical application, why should one specify a precise dtype during array initialization?
Answer: To allow NumPy to optimize memory bandwidth and cache usage.. Smaller, precise dtypes like int8 or float32 occupy less memory, allowing more data to fit into the CPU cache, reducing cache misses. Option 1 is incorrect as NumPy doesn't cast to Python types; option 2 is not the direct purpose of dtypes; option 3 is independent of the math logic.
From lesson: NumPy vs Python Lists — Speed Comparison
If you are processing a small dataset (e.g., 5 elements), why might using a Python list be faster than a NumPy array?
Answer: NumPy has high overhead for initializing metadata and checking array structures.. NumPy incurs 'setup' overhead to handle indices, strides, and memory metadata, which is expensive for tiny arrays but negligible for large ones. Python lists are simple pointers that have very low overhead for small collections. The other options are either incorrect or unrelated to speed.
From lesson: NumPy vs Python Lists — Speed Comparison
You have a large 2D array and need to perform operations that involve constant row-wise access. Which memory layout strategy will likely minimize cache misses?
Answer: Store the data in C order. C-order stores rows contiguously, making row-wise access efficient. Fortran-order stores columns contiguously, making column-wise access efficient. Non-contiguous buffers and object arrays significantly degrade performance due to pointer chasing and memory fragmentation.
From lesson: Memory Layout — C vs Fortran order
What happens to the memory layout when you perform 'arr.T' on a C-contiguous NumPy array?
Answer: The array remains a view and its memory layout status changes to F-contiguous. Transposing a C-contiguous array creates a view where the strides are inverted. While the underlying memory buffer remains in the same physical order, the view is now F-contiguous in its access pattern. It does not reorder the physical data.
From lesson: Memory Layout — C vs Fortran order
If you are passing a NumPy array to a legacy library that strictly requires Fortran-style memory layout, which function ensures your array is formatted correctly without unnecessary work?
Answer: np.asfortranarray(arr). np.asfortranarray() checks if the array is already Fortran-contiguous. If it is, it returns the original array; otherwise, it creates a copy in the correct layout. Other options either create C-order data or ignore the requirement entirely.
From lesson: Memory Layout — C vs Fortran order
How does the 'order' parameter affect the output of 'np.ravel()'?
Answer: It dictates whether the array is flattened by rows (C) or columns (F). The 'order' parameter in 'ravel()' defines how the elements are traversed: 'C' traverses row by row, while 'F' traverses column by column. The other options are incorrect as they misdescribe the primary function of the order argument.
From lesson: Memory Layout — C vs Fortran order
A function is running significantly slower than expected. You observe the input array is Fortran-contiguous, but the function iterates over it using 'for i in range(rows): for j in range(cols):'. Why is this slow?
Answer: The inner loop is iterating over the first index, which jumps across columns in F-order. In Fortran order, elements of the first column are adjacent in memory. Iterating by row (the first index) in a nested loop forces the computer to jump to distant memory addresses for every step, causing cache misses. Options 1 and 4 are false generalizations, and while vectorization is preferred, the layout mismatch is the specific performance bottleneck here.
From lesson: Memory Layout — C vs Fortran order
Which of the following is the most efficient way to compute the square root of every element in a large NumPy array 'arr'?
Answer: Use the ufunc: np.sqrt(arr). np.sqrt is a vectorized universal function. It executes in compiled C code. List comprehensions and loops involve Python object overhead, making them significantly slower. map() also fails to leverage NumPy's internal optimization.
From lesson: Vectorization Best Practices
You have a 1D array 'x' and a 2D array 'y'. You want to add 'x' to each row of 'y'. What allows this without explicit loops?
Answer: Broadcasting rules that align the dimensions of x and y. Broadcasting allows arrays with different shapes to be combined if the trailing dimensions are compatible. The other options involve either unnecessary memory overhead or logic that doesn't exist in NumPy.
From lesson: Vectorization Best Practices
What is the primary reason to avoid np.append inside a loop?
Answer: It triggers a complete memory reallocation and copy of the array on every call. NumPy arrays have fixed sizes. np.append creates a new array in memory every time. Doing this in a loop results in quadratic time complexity. Pre-allocation is the standard practice.
From lesson: Vectorization Best Practices
Consider an array 'data' of shape (100, 100). How do you efficiently sum all elements in every row?
Answer: data.sum(axis=1). Axis 1 represents the column index, so summing across axis 1 collapses the columns, resulting in the sum of each row. Axis 0 would sum the columns, None sums everything, and a for loop is inefficient.
From lesson: Vectorization Best Practices
How should you initialize an array of 1,000,000 zeros to be filled later?
Answer: arr = np.zeros(1000000). np.zeros creates a contiguous block of memory allocated for the correct size instantly. Using a list comprehension or repeated appends creates a list first, then converts it, which is memory-intensive and slow.
From lesson: Vectorization Best Practices
What happens when you perform arr1 + arr2 where arr1 is shape (3, 1) and arr2 is shape (3,)?
Answer: The arrays are broadcast to shape (3, 3). NumPy broadcasts trailing dimensions; the (3, 1) and (3,) arrays result in a (3, 3) shape. A ValueError isn't raised because they are compatible, and concatenation or static size results are incorrect.
From lesson: NumPy Interview Questions
If you create a slice 'sub = arr[0:2, :]', how does modifying 'sub' affect 'arr'?
Answer: It modifies the original array because slices return views. Slicing an array creates a view, meaning both variables point to the same memory. Deep copies are not default behavior; the other options ignore the view mechanics of NumPy.
From lesson: NumPy Interview Questions
Which function is best for replacing values in an array based on a condition?
Answer: np.where(). np.where(condition, x, y) is specifically designed to choose elements based on a boolean mask. The other functions are either not part of the NumPy API or intended for different data structures.
From lesson: NumPy Interview Questions
What is the primary benefit of using vectorized operations in NumPy?
Answer: It shifts the computation loop from the Python interpreter to optimized C code. Vectorization moves loops into compiled C/Fortran code, drastically increasing speed. It does not resolve Python's interpreter lock, nor does it inherently change memory usage or allow mixed types (arrays are homogeneous).
From lesson: NumPy Interview Questions
Given two arrays 'a' and 'b' of the same shape, what does 'a * b' compute?
Answer: The element-wise product. In NumPy, the * operator is strictly for element-wise multiplication. Dot product requires @ or .dot(), cross product uses np.cross(), and the outer product uses np.outer().
From lesson: NumPy Interview Questions
What is the result of performing arr1 * arr2 if both are NumPy arrays of the same shape?
Answer: A new array containing the element-wise product. NumPy arrays perform element-wise multiplication by default. The dot product requires the dot() method, lists use concatenation, and broadcasting only occurs if shapes are different.
From lesson: NumPy Coding Challenges
Given an array 'a' of shape (3, 4), what happens if you call a.reshape(4, 3)?
Answer: It creates a new array with the new dimensions without changing the data order. Reshape reorders the elements into the new shape based on the original data buffer. It does not transpose (which uses the transpose method) and creates a new view, it does not modify the original in-place.
From lesson: NumPy Coding Challenges
If you perform a = np.array([1, 2, 3]); b = a[:2]; b[0] = 9, what is the value of a[0]?
Answer: 9. Slicing an array returns a view, not a copy. Therefore, modifying the view 'b' directly affects the original array 'a'. The other options are incorrect because they assume a copy was made.
From lesson: NumPy Coding Challenges
What is the primary benefit of using NumPy's Boolean masking?
Answer: To quickly select or filter elements based on a condition without explicit loops. Boolean masking allows for vectorized filtering, which is the most efficient and readable way to handle conditions in NumPy. It does not sort data or compress memory.
From lesson: NumPy Coding Challenges
When performing an operation between arrays of shape (3, 1) and (1, 3), what is the shape of the result?
Answer: (3, 3). NumPy uses broadcasting rules to expand the dimensions of both arrays to (3, 3) to perform the operation. It is not an error because the trailing dimensions are compatible for broadcasting.
From lesson: NumPy Coding Challenges