NumPy is an open-source Python library used for numerical computing and handling large multi-dimensional arrays efficiently. In interviews, questions on NumPy are often asked to evaluate your understanding of array operations, mathematical functions and performance optimization. Below are some of the most frequently asked interview questions covering key NumPy topics.
1. What is NumPy and how to create a NumPy array?
NumPy is used for numerical and scientific computing. It offers support for arrays, matrices and a variety of mathematical operations that can effectively operate on these arrays.
We can create NumPy arrays using various methods. Here are some common ways to create NumPy arrays:
2. What are the main features of Numpy?
Here are some main features of the NumPy:
- Fast and Efficient
- Mathematical Functions
- Broadcasting
- Integration with other libraries
- Multi-dimensional arrays
- Indexing and Slicing
- Memory Management
3. What is the difference between np.arange() and np.linspace()?
np.arange() and np.linspace() are NumPy functions used to generate sequences of numbers. np.arange() generates values using a fixed step size, whereas np.linspace() generates a fixed number of evenly spaced values between a start and an end value.
- Generates values using a specified step size.
- The end value is excluded.
- The number of values depends on the step size.
- Best for sequences with a known interval.
- Goal: Generate numbers with a fixed increment.
- Generates a specified number of evenly spaced values.
- The end value is included by default.
- The spacing is automatically calculated.
- Best for plotting graphs and numerical computations.
- Goal: Generate a fixed number of evenly spaced values.
4. How do you calculate the dot product of two NumPy arrays?
Calculating the dot product of two NumPy arrays we used numpy.dot() function and we also used the @ operator:
1. Using numpy.dot() function:
numpy.dot(a, b)
a: The first input array (NumPy array).
b: The second input array (NumPy array).
2. Using the @ operator
a @ b
Both methods will return the dot product of the two arrays as a scalar value.
5. What is the difference between a shallow copy and a deep copy in NumPy?
In NumPy, a shallow copy (view) shares the same underlying data as the original array, so changes in one array affect the other. A deep copy creates a completely independent copy of the array, so changes to one array do not affect the other.
Shallow Copy (View)
- Shares the same memory as the original array.
- Changes made to the copy also affect the original array.
- Created using .view().
- Memory-efficient because no new data is copied.
- Goal: Create another view of the same data.
Deep Copy
- Creates a new independent copy of the array.
- Changes made to the copy do not affect the original array.
- Created using .copy().
- Requires additional memory.
- Goal: Create a completely separate array.
6. What is the difference between np.copy(), .view() and = assignment?
= assignment, .view(), and np.copy() (or .copy()) are different ways of creating another array reference in NumPy. = assignment creates another reference to the same array, .view() creates a new array object that shares the same data (shallow copy), and np.copy() creates a completely independent copy of the array (deep copy).
- Creates another reference to the same array.
- No new array or memory is created.
- Changes through either variable affect the same array.
- Goal: Create another reference to the existing array.
.view()
- Creates a new array object that shares the same underlying data.
- New object, but shared memory.
- Changes in one array are reflected in the other.
- Goal: Create a shallow copy without duplicating data.
- Creates a completely independent copy of the array.
- Allocates new memory.
- Changes to the copied array do not affect the original.
- Goal: Create a deep copy.
7. How do you reshape a NumPy array?
We can reshape a NumPy array by using the reshape() method or the np.reshape() function. it help us to change the dimensions of the array and keep all the elements constant.
1. Using the reshape() method:
array1= original_array.reshape(new_shape)
2. Using the np.reshape() function:
array1 = np.reshape(original_array, new_shape)
In both cases, original_array is the existing NumPy array you want to reshape and new_shape is a tuple specifying the desired shape of the new array.
8. What is np.newaxis and np.expand_dims() used for?
Both are used to add a new dimension (axis) to an existing NumPy array without changing its data — commonly needed to make shapes compatible for broadcasting (e.g., turning a 1-D array into a row or column vector).
import numpy as np
arr = np.array([1, 2, 3]) # shape (3,)
row = arr[np.newaxis, :] # shape (1, 3)
col = arr[:, np.newaxis] # shape (3, 1)
col2 = np.expand_dims(arr, axis=1) # same as col, shape (3, 1)
- np.newaxis is just an alias for None and is typically used inside indexing.
- np.expand_dims() is a function call that does the same thing and is often preferred for readability in code.
9. What does the axis parameter mean in NumPy (axis=0 vs axis=1)?
Many NumPy functions (sum, mean, max, sort, concatenate, etc.) accept an axis argument that controls which direction the operation is applied along in a multi-dimensional array. T
- axis=0 → operate down the rows, i.e., collapse/combine values column-wise (the result has one value per column).
- axis=1 → operate across the columns, i.e., collapse/combine values row-wise (the result has one value per row).
- If axis is omitted, the operation applies to the entire flattened array.
10. How to perform element-wise operations on NumPy arrays?
To perform element-wise operations on NumPy arrays, you can use standard arithmetic operators. NumPy automatically applies these operations element-wise when you use them with arrays of the same shape.
import numpy as np
# Create two NumPy arrays
array1 = np.array([1, 2, 3, 4, 5])
array2 = np.array([6, 7, 8, 9, 10])
# Perform element-wise operations
result_addition = array1 + array2
result_subtract = array1 - array2
result_multiply = array1 * array2
result_divide = array1 / array2
result_power = np.power(array1, 2)
# Print results
print("Addition:", result_addition)
print("Subtraction:", result_subtract)
print("Multiplication:", result_multiply)
print("Division:", result_divide)
print("Power:", result_power)
Output:
Addition: [ 7 9 11 13 15]
Subtraction: [-5 -5 -5 -5 -5]
Multiplication: [ 6 14 24 36 50]
Division: [0.16666667 0.28571429 0.375 0.44444444 0.5 ]
Power: [ 1 4 9 16 25]
11. Why does dividing by zero in NumPy give a warning instead of crashing, and how do you control that behaviour?
- Unlike plain Python (1/0 raises ZeroDivisionError), NumPy is built for array-wide numerical computing, so it doesn't want one bad element to halt an entire computation.
- Instead, invalid floating-point operations (divide-by-zero, invalid operations like 0/0, overflow, underflow) produce inf, -inf, or nan and emit a RuntimeWarning.
- You can control this behaviour with np.errstate() (as a context manager) or np.seterr() (globally) — commonly used to intentionally suppress expected warnings.
12. How to generate random numbers with NumPy?
NumPy provides a wide range of functions for generating random numbers. You can generate random numbers from various probability distributions, set seeds for reproducibility and more. Here are some common ways to generate random numbers with NumPy:
1. Using np.random.rand()
Generating a Random Float between 0 and 1 using np.random.rand()
random_float = np.random.rand()
2. Using np.random.randint()
Generating a Random Integer within a Range using np.random.randint().
random_integer = np.random.randint()
3. Using np.random.randn()
Generates random floats from the standard normal (Gaussian) distribution.
random_float = np.random.rand()
4. Using np.random.seed()
We can set a seed using np.random.seed() to ensure that the generated random numbers are reproducible.
np.random.seed(seed_value)
13. What is the difference between the legacy np.random.seed() and the newer np.random.default_rng() Generator API?
Both np.random.seed() and np.random.default_rng() are used to generate random numbers in NumPy.
np.random.seed() (Legacy API)
- Initializes the global random number generator.
- All random functions use the same global state.
- Changing the seed affects the entire program.
- Older approach, maintained mainly for backward compatibility.
- Goal: Reproduce random sequences using the legacy API.
np.random.default_rng() (Generator API)
- Creates an independent Generator object.
- Each generator maintains its own random state.
- Does not affect other random number generators.
- Uses the newer PCG64 algorithm by default.
- Recommended for all new NumPy code.
- Goal: Generate reproducible random numbers with independent generators.
14. How can you create a NumPy array from a Python list?
We can create a NumPy array from a Python list using the np.array() constructor provided by NumPy.
python_list = [1, 2, 3, 4, 5]
numpy_array = np.array(python_list)
15. What is the difference between np.array() and np.asarray()?
Both np.array() and np.asarray() are used to create NumPy arrays. However, np.array() creates a new array by default (copying the data if needed), whereas np.asarray() converts the input to a NumPy array without copying the data if it is already an array.
- Creates a NumPy array from lists, tuples, or other array-like objects.
- Copies the data by default.
- Can create an independent array.
- Suitable when you need a separate copy of the data.
- Goal: Create a new NumPy array.
- Converts the input into a NumPy array.
- Does not copy the data if the input is already a NumPy array.
- Returns the original array whenever possible.
- More memory-efficient and faster.
- Goal: Avoid unnecessary copying.
16. How can you access elements in a NumPy array based on specific conditions?
We can access elements in a NumPy array based on specific conditions using boolean indexing. Boolean indexing allows us to create true and false values based on a condition.
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
condition = arr > 3
selected_elements = arr[condition]
print("Selected Elements (greater than 3):", selected_elements)
Output:
Selected Elements (greater than 3): [4 5]
17. What is np.where() and how is it used to query a NumPy array?
np.where() is one of NumPy's most-used "querying" functions. It has two forms:
1. Condition + two choices (like a vectorized if-else): returns a new array, choosing values from x where the condition is True and from y where it is False.
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
result = np.where(arr > 3, arr, 0) # keep value if >3, else 0
print(result)
Output:
[0 0 0 4 5]
2. Condition only: returns the indices where the condition is True — this is effectively a "query" that tells you where in the array a condition holds.
indices = np.where(arr > 3)
print(indices) # (array([3, 4]),)
18. What is the difference between np.where() and boolean indexing?
Both np.where() and Boolean Indexing are used to filter or modify data in NumPy based on conditions. However, Boolean Indexing directly selects elements that satisfy a condition, whereas np.where() returns indices or allows conditional replacement of values.
- Selects elements that satisfy a condition.
- Returns only the matching values.
- Simple and readable for filtering data.
- Commonly used to extract subsets of an array.
- Goal: Filter data based on a condition.
- Evaluates a condition and returns indices or values based on the arguments.
- With one argument, returns the indices where the condition is True.
- With three arguments, returns values based on a condition (if-else behavior).
- Commonly used for conditional replacement or locating elements.
- Goal: Find indices or perform conditional selection.
19. What is np.select() and when would you use it over np.where()?
np.select() extends np.where() to handle multiple conditions at once, each with its own choice — similar to a CASE WHEN / if-elif-elif-else chain, but vectorized.
import numpy as np
arr = np.array([-5, 0, 5, 15, 25])
conditions = [arr < 0, arr < 10, arr < 20]
choices = ["negative", "small", "medium"]
result = np.select(conditions, choices, default="large")
print(result)
Output:
['negative' 'small' 'small' 'medium' 'large']
- Nesting np.where() calls for more than one condition quickly becomes unreadable.
- np.select() is the cleaner and recommended choice once you have 3+ conditions.
20. What does np.nonzero() return, and how is it different from np.where()?
np.nonzero(arr) returns the indices of all elements that are non-zero (or, when given a boolean array, all elements that are True) — as a tuple of arrays, one per dimension.
import numpy as np
arr = np.array([0, 3, 0, 7, 9])
print(np.nonzero(arr)) # (array([1, 3, 4]),)
- np.where(condition) (single-argument form) is actually implemented as a call to np.nonzero(condition) internally — they return identical results in that case.
- The difference is purely in intent/readability: use np.nonzero() when checking for non-zero/True entries directly, and use np.where() when you're evaluating a condition expression.
21. How do you find the row and column positions of all elements greater than a given value in a 2D array?
import numpy as np
arr = np.array([[1, 2],[3, 4]])
print(np.argwhere(arr > 2))
Output:
[[1 0]
[1 1]]
22. How do you find the correct index to insert a value into a sorted array so it stays sorted?
import numpy as np
sorted_arr = np.array([1, 3, 5, 7, 9])
print(np.searchsorted(sorted_arr, 6))
Output:
3
23. How do you extract all elements from an array that are divisible by 3?
import numpy as np
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
print(np.extract(arr % 3 == 0, arr))
Output:
[3 6 9]
24. How do you select array elements at specific index positions?
import numpy as np
arr = np.array([10, 20, 30, 40, 50])
print(np.take(arr, [0, 2, 4]))
Output:
[10 30 50]
25. How do you replace array elements at specific index positions with new values?
import numpy as np
arr = np.array([10, 20, 30, 40, 50])
np.put(arr, [1, 3], [99, 88])
print(arr)
Output:
[10 99 30 88 50]
26. What are some common data types supported by NumPy?
In NumPy there are so many data types that are used to specify the type of data which stored in array. This data type provide control that how data stored in memory during operations. Some common data types supported by NumPy include:
- int
- float
- complex
- bool
- object
- datetime
27. How do you convert a NumPy array from one dtype to another?
Use .astype() to explicitly convert an array to a different data type. It always returns a new copy — it never modifies the original array in place, which avoids silent, unexpected upcasting/downcasting bugs.
import numpy as np
arr = np.array([1.9, 2.7, 3.1])
ints = arr.astype(np.int32) # truncates the decimal part, does NOT round
print(ints) # [1 2 3]
print(arr.dtype) # float64 -- original is untouched
print(ints.dtype) # int32
28. What are structured (record) arrays in NumPy?
- A structured array lets each element hold multiple named fields of different data types — similar to a row in a database table or a lightweight version of a Pandas DataFrame, but backed by a plain ndarray.
- Structured arrays are useful for heterogeneous, table-like data when you want NumPy's performance without pulling in Pandas.
29. How can you concatenate two NumPy arrays vertically?
We can concatenate two NumPy arrays vertically (along the rows) using the np.vstack() function or the np.concatenate() function with the axis parameter set to 0. Here's how to do it with both methods:
1. Using np.vstack()
array= np.vstack((array1, array2))
2. Using np.concatenate() with axis
array= np.concatenate((array1, array2), axis=0)
30. How do you split a NumPy array?
NumPy provides the reverse operation of stacking/concatenating — splitting one array into multiple sub-arrays:
- np.split(arr, n): Splits into ntally (column-wise), equivalent to axis=1.
- np.vsplit(arr, n): Splits verticall equal parts along an axis; raises an error if it can't split evenly.
- np.array_split(arr, n): Same as np.split(), but allows uneven splits.y (row-wise), equivalent to axis=0.
- np.hsplit(arr, n): Splits horizon
31. What is np.pad() used for?
np.pad() adds extra values (padding) around the edges of an array — commonly needed before running convolutions/sliding-window operations, or to make arrays a uniform size.
32. What is Matrix Inversion in NumPy?
- Matrix inversion in NumPy refers to the process of finding the inverse of a square matrix.
- The identity matrix is produced when multiplying the original matrix by the inverse of the matrix.
- In other words, if A is a square matrix and A^(-1) is its inverse, then A * A^(-1) = I, where I is the identity matrix.
- NumPy provides a convenient function called numpy.linalg.inv() to compute the inverse of a square matrix. Here's how you can use it:
import numpy as np
# Define a square matrix
A = np.array([[1, 2, 3],
[0, 1, 4],
[5, 6, 0]])
# Calculate the inverse of the matrix
A_inverse = np.linalg.inv(A)
# Print results
print("Original Matrix:\n", A)
print("Inverse Matrix:\n", A_inverse)
Output:
Original Matrix:
[[ 1 2 3]
[ 0 1 4]
[ 5 6 0]]Inverse Matrix:
[[-24. 18. 5.]
[ 20. -15. -4.]
[ -5. 4. 1.]]
33. How do you solve a system of linear equations using NumPy?
Rather than manually inverting a matrix (A⁻¹b), which is numerically less stable and slower, NumPy provides numpy.linalg.solve() to directly solve Ax = b for x.
import numpy as np
# 2x + y = 5
# x + 3y = 10
A = np.array([[2, 1], [1, 3]])
b = np.array([5, 10])
x = np.linalg.solve(A, b)
print(x)
Output:
[1. 3.]
34. What do np.trace() and np.diag() do?
Both work with the diagonal of a matrix but serve different purposes:
- np.trace(matrix) returns the sum of the elements on the main diagonal — a single number.
- np.diag(matrix) extracts the diagonal elements as a 1-D array (or, given a 1-D array, builds a 2-D matrix with that array on the diagonal).
35. Define the var and mean function in NumPy.
In NumPy, the var function is used to compute the variance of elements in an array or along a specified axis. Variance is a measure of the spread or dispersion of data points.
np.var(a, axis=None, dtype=None)
- a: The input array for which you want to calculate the variance.
- axis: Axis or axes along which the variance is computed. If not specified, the variance is calculated for the whole array. It can be an integer or a tuple of integers to specify multiple axes.
- dtype: The data type for the returned variance. If not specified, the data type is inferred from the input array.
The arithmetic mean (average) in NumPy can be calculated using numpy.mean(). This method tallies elements in an array, whether it be along a specified axis or the whole array, if no axis is explicitly mentioned. The summation of all elements is then divided by the overall number of elements which provides the average.
numpy.mean(a, axis=None)
- a: The input array for which you want to calculate the mean.
- axis : The axis or axes along which the mean is computed. If not specified, the mean is calculated over the entire array.
36. Convert a multidimensional array to 1D array.
You can convert a multidimensional array to a 1D array which is also known as flattening the array in NumPy using various methods. Two common methods are using for the Convert a multidimensional array to 1D array.
1. Using flatten():
# Create a multidimensional array
multidimensional_array = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# Use the flatten() method to convert it to a 1D array
one_dimensional_array = multidimensional_array.flatten()
print("one dimensional array", one_dimensional_array)
Output:
one dimensional array [1 2 3 4 5 6 7 8 9]
2. Using ravel():
# Create a multidimensional array
multidimensional_array = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# Use the ravel() method to convert it to a 1D array
one_dimensional_array = multidimensional_array.ravel()
print("one dimensional array", one_dimensional_array)
Output:
one dimensional array [1 2 3 4 5 6 7 8 9]
Both of these methods will flatten the multidimensional array into a 1D array. The primary difference between them:
- Flatten() returns a new copy of the array. Any modifications in the flattened array do not affect the original array
- Ravel() returns a flattened view of the original array whenever possible. Changes made to the raveled array may affect the original array since they share the same data in memory.
37. How can you identify outliers in a NumPy array?
Identifying and removing outliers in a NumPy array involves several steps. Outliers are data points that significantly deviate from the majority of the data and can adversely affect the results of data analysis. Here's a general approach to identify and remove outliers:
Identifying Outliers:
1. Calculate Descriptive Statistics: Compute basic statistics like the mean and standard deviation of the array to understand the central tendency and spread of the data.
import numpy as np
# Sample data
arr = np.array([10, 12, 12, 13, 12, 11, 300, 14, 13, 12])
# Calculate mean and standard deviation
mean = np.mean(arr)
std = np.std(arr)
# Define threshold (e.g., 2 standard deviations from mean)
threshold = 2
outliers = arr[np.abs(arr - mean) > threshold * std]
print("Outliers:", outliers)
Output:
Outliers: [300]
2. Using IQR: IQR (Interquartile Range) is the difference between the 75th percentile (Q3) and the 25th percentile (Q1), representing the spread of the middle 50% of the data.
import numpy as np
arr = np.array([10, 12, 12, 13, 12, 11, 300, 14, 13, 12])
# Calculate Q1 (25th percentile) and Q3 (75th percentile)
Q1 = np.percentile(arr, 25)
Q3 = np.percentile(arr, 75)
IQR = Q3 - Q1
# Define bounds
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# Identify outliers
outliers = arr[(arr < lower_bound) | (arr > upper_bound)]
print("Outliers:", outliers)
Output:
Outliers: [ 10 300]
38. What is np.clip() used for?
- np.clip() limits (clips) the values in an array to a given [min, max] range any value below the minimum is set to the minimum, and any value above the maximum is set to the maximum.
- It's a common, simpler alternative to outlier removal when you want to cap extreme values instead of discarding them.
39. How do you remove missing or null values from a NumPy array?
We can remove null values using numpy.isnan() method.
import numpy as np
my_array = np.array([1, 2, np.nan, 4, np.nan, 6])
# Create a mask for NaN values
mask = np.isnan(my_array)
# Use the inverse of the mask to filter out missing values
filtered_array = my_array[~mask]
print("Original Array:", my_array)
print("Filtered Array (without NaNs):", filtered_array)
Output:
Original Array: [ 1. 2. nan 4. nan 6.]
Filtered Array (without NaNs): [1. 2. 4. 6.]
We can filter out missing or null data using a masked array or a boolean mask.
import numpy as np
# Create a NumPy array with missing values (NaN)
arr = np.array([1.0, 2.0, np.nan, 4.0, 5.0])
# Create a masked array where missing values are masked
masked_arr = np.ma.masked_invalid(arr)
# Access only non-missing values
clean_data = masked_arr.compressed()
print(clean_data)
Output:
[1. 2. 4. 5.]
40. What is the difference between slicing and indexing in NumPy?
Indexing and Slicing are techniques used to access elements in a NumPy array. Indexing retrieves a single element (or a specific row/column), whereas Slicing retrieves a range of elements and returns a view of the original array whenever possible.
Indexing
- Accesses a single element or a specific row/column.
- Uses the position (index) of the element.
- Returns a scalar value (or a single row/column).
- Used when only one specific value is needed.
- Goal: Retrieve individual elements.
Slicing
- Accesses a range of elements.
- Uses the syntax start:stop:step.
- Returns a view of the original array (in most cases).
- Used to extract subarrays.
- Goal: Retrieve a subset of the array.
41. How can you create array with same values.
We can create a NumPy array with the same values using various functions and methods depending on your specific needs. Here are a few common approaches:
1. Using numpy.full(): You can use the numpy.full() function to create an array filled with a specific value. This function takes two arguments: the shape of the array and the fill value.
# Create a 1D array with 5 elements, all set to 7
arr = np.full(5, 7)
2. Using Broadcasting: If you want to create an array of the same value repeated multiple times, you can use broadcasting with NumPy.
# Create a 1D array with 5 elements, all set to 7
arr = 7 * np.ones(5)
# Create a 2D array with dimensions 3x4, all elements set to 2.0
arr_2d = 2.0 * np.ones((3, 4))
3. Using list comprehension: You can also create an array with the same values using a list comprehension and then converting it to a NumPy array.
# Create a 1D array with 5 elements, all set to 7
arr = np.array([7] * 5)
# Create a 2D array with dimensions 3x4, all elements set to 2.0
arr_2d = np.array([[2.0] * 4] * 3)
42. What is the difference between np.tile() and np.repeat()?
Both np.tile() and np.repeat() are used to replicate data in NumPy, but they do so differently. np.tile() repeats the entire array or pattern, whereas np.repeat() repeats individual elements of the array.
- Repeats the entire array a specified number of times.
- Preserves the original pattern.
- Can repeat arrays along multiple dimensions.
- Used to create larger patterned arrays.
- Goal: Repeat the whole array.
- Repeats each element individually.
- Number of repetitions can be specified for each element.
- Useful for duplicating values.
- Goal: Repeat individual elements.
43. What is a masked array in NumPy.
- A masked array in NumPy is a special type of array that includes an additional Boolean mask, which marks certain elements as invalid or masked.
- This allows you to work with data that has missing or invalid values without having to modify the original data.
- Masked arrays are particularly useful when dealing with real-world datasets that may have missing or unreliable data points.
Example: Creating and Using a Masked Array
import numpy as np
import numpy.ma as ma
# Create a normal NumPy array
data = np.array([1, 2, -999, 4, 5])
# Mask invalid values (-999 treated as missing data)
masked_data = ma.masked_equal(data, -999)
print("Original Data:", data)
print("Masked Data:", masked_data)
# Perform operations while ignoring masked values
mean_value = masked_data.mean()
print("Mean (ignoring masked values):", mean_value)
Output:
Original Data: [ 1 2 -999 4 5]
Masked Data: [1 2 -- 4 5]
Mean (ignoring masked values): 3.0
44. What is broadcasting in numpy?
Broadcasting in NumPy is the ability of NumPy to perform arithmetic operations on arrays of different shapes and sizes without explicitly replicating the data.
- If two arrays have different shapes, NumPy automatically expands the smaller array along the mismatched dimensions so they can be combined.
- This makes code more efficient and avoids unnecessary memory usage.
1. Broadcasting Scalar
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
# Broadcasting scalar 10 across all elements
result = arr + 10
print(result)
Output:
[11 12 13 14 15]
2. Arrays with Different Shapes
# 2D array
A = np.array([[1, 2, 3],
[4, 5, 6]])
# 1D array
B = np.array([10, 20, 30])
# Broadcasting B across each row of A
result = A + B
print(result)
Output:
[[11 22 33]
[14 25 36]]
45. What are the rules NumPy follows for broadcasting?
NumPy compares array shapes element-wise, starting from the trailing (rightmost) dimension, and two dimensions are compatible when:
- They are equal, or
- One of them is 1 (it gets "stretched" to match the other), or
- One of the arrays simply has fewer dimensions (missing dimensions are treated as size 1 and padded on the left).
46. What is np.meshgrid() used for?
- np.meshgrid() takes two (or more) 1-D coordinate arrays and produces 2-D coordinate grids representing every combination of x and y values.
- It's heavily used in plotting (contour/surface plots) and evaluating functions over a 2-D grid.
- Each position (X[i,j], Y[i,j]) gives one coordinate pair on the grid — useful for evaluating Z = f(X, Y) across a whole 2-D surface without writing nested loops.
47. How do you sort a NumPy array in ascending or descending order?
To arrange a NumPy array in both ascending and descending order we use numpy.sort() to create an ascending one and numpy.argsort() for a descending one. Here’s how to do it:
1. Ascending Order: You can use the numpy.sort() function to sort your array in ascending order. The function will return a new sorted array, while still leaving the original array unchanged.
# Create a NumPy array
my_array = np.array([3, 1, 2, 4, 5])
# Sort the array in ascending order
sorted_array = np.sort(my_array)
print("Ascending: ",sorted_array)
Output:
Ascending: [1 2 3 4 5]
2. Sorting in Descending Order: To sort a NumPy array in descending order, you can use the numpy.argsort() function to obtain the indices that would sort the array in ascending order and then reverse those indices to sort in descending order.
# Create a NumPy array
my_array = np.array([3, 1, 2, 4, 5])
# Get indices for descending order and use them to reorder
descending_arr = arr[np.argsort(-arr)]
print("Descending:", descending_arr)
Output:
Descending: [ 5 4 3 2 1]
48. How are NumPy Arrays better than Lists in Python?
NumPy arrays offer several advantages over Python lists when it comes to numerical and scientific computing. Here are some key reasons why NumPy arrays are often preferred:
- Performance
- Vectorization
- Broadcasting
- Multidimensional Arrays
- Memory Management
- Standardization
49. Difference between np.reshape() and np.resize()
Both np.reshape() and np.resize() are used to change the shape of a NumPy array, but they behave differently.
- Changes the shape of an array without changing its data.
- The total number of elements must remain the same.
- Raises an error if the new shape is incompatible.
- Returns a reshaped array (view whenever possible).
- Goal: Rearrange existing elements into a new shape.
- Changes the shape and can change the size of the array.
- If the new size is larger, elements are repeated.
- If the new size is smaller, extra elements are discarded.
- Returns a new resized array.
- Goal: Resize an array by adding or removing elements.
50. Discuss uses of vstack() and hstack() functions?
np.vstack() and np.hstack() are NumPy functions used to combine arrays. np.vstack() stacks arrays vertically (row-wise), whereas np.hstack() stacks arrays horizontally (column-wise).
- Stacks arrays vertically (one below another).
- Increases the number of rows.
- Arrays must have the same number of columns.
- Equivalent to stacking along axis = 0.
- Goal: Combine arrays row-wise.
- Stacks arrays horizontally (side by side).
- Increases the number of columns.
- Arrays must have the same number of rows.
- Equivalent to stacking along axis = 1 (for 2D arrays).
- Goal: Combine arrays column-wise.
51. How to Get the eigen values and determinant of a matrix.
With the help of np.eigvals() method, we can get the eigen values of a matrix by using np.eigvals() method.
np.linalg.eigvals(matrix)
The Determinant of a square matrix is a unique number that can be derived from a square matrix. Using the numpy.linalg.det() method, NumPy gives us the ability to determine the determinant of a square matrix.
numpy.linalg.det(array)
52. How to compare two NumPy arrays?
Method 1: Using == operator: We generally use the == operator to compare two NumPy arrays to generate a new array object. Call ndarray.all() with the new array object as ndarray to return True if the two NumPy arrays are equivalent.
import numpy as np
arr1 = np.array([1, 2, 3])
arr2 = np.array([1, 2, 3])
arr3 = np.array([1, 4, 3])
print((arr1 == arr2).all()) # True
print((arr1 == arr3).all()) # False
Output:
True
False
Method 2: Using array_equal(): This array_equal() function checks if two arrays have the same elements and same shape.
numpy.array_equal(arr1, arr2)
53. Why should you use np.allclose() instead of == when comparing floating-point arrays?
- Floating-point arithmetic is not perfectly precise — operations like 0.1 + 0.2 don't produce exactly 0.3 due to how floats are represented in binary.
- Using == on such values can give surprising False results even when the numbers are "mathematically" equal.
- np.allclose(a, b, rtol=1e-05, atol=1e-08) checks whether values are equal within a small tolerance, which is the correct way to compare floating-point arrays for equality in almost all real-world numerical code.
54. Calculate the QR decomposition of a given matrix using NumPy.
A matrix's decomposition into the form "A=QR," where Q is an orthogonal matrix and R is an upper-triangular matrix and it is known as QR factorization. We can determine the QR decomposition of a given using matrix.linalg.qr().
numpy.linalg.qr(a, mode=’reduced’)
- a: matrix(M,N) which needs to be factored.
- mode: it is optional.
55. What are ndarrays in NumPy?
An ndarray also known as "N-dimensional array" is a fundamental data structure used in NumPy for effectively storing and manipulating data, particularly numerical data. It is:
- Multidimensional: Can represent 1D, 2D, 3D or higher-dimensional arrays.
- Homogeneous: All elements must have the same data type.
- Efficient: Optimized for mathematical and array-oriented operations.
56. What is the difference between C-order and F-order memory layout in NumPy, and what are strides?
NumPy stores an array's data as one contiguous block of memory. Strides tell NumPy how many bytes to skip in memory to move one step along each axis — this is how NumPy maps multi-dimensional indices onto that flat memory block without copying data on operations like reshape, transpose, or slicing.
- C-order (row-major, the default): elements of a row are stored next to each other in memory. Faster for row-wise operations.
- F-order (column-major, Fortran style): elements of a column are stored next to each other in memory. Faster for column-wise operations.
57. What is Vectorization in Numpy?
Vectorization in NumPy means performing operations on entire arrays or vectors at once without using explicit loops. NumPy internally uses optimized C code, so vectorized operations are much faster than iterating through elements in Python.
- Eliminates the need for for loops.
- Operations are applied element-wise on the whole array.
- Improves performance and makes code more concise.
import numpy as np
# Without vectorization (using loop)
arr = np.array([1, 2, 3, 4, 5])
squared_loop = []
for x in arr:
squared_loop.append(x ** 2)
print("Using loop:", squared_loop)
# With vectorization
squared_vectorized = arr ** 2
print("Using vectorization:", squared_vectorized)
Output:
Using loop: [1, 4, 9, 16, 25]
Using vectorization: [ 1 4 9 16 25]
58. What are ufuncs (universal functions) in NumPy?
A ufunc is a function that operates element-wise on ndarrays, supports broadcasting, and is implemented in compiled C code for speed. Vectorized operations like np.add, np.subtract, np.sqrt, np.exp, and even the +/-/* operators are all backed by ufuncs under the hood.
import numpy as np
arr = np.array([1, 4, 9, 16])
print(np.sqrt(arr)) # [1. 2. 3. 4.] -- np.sqrt is a ufunc
print(np.add(arr, 1)) # [ 2 5 10 17] -- np.add is a ufunc
59. How do you apply a custom function to each row or column of a 2D array?
1. np.apply_along_axis(func, axis, arr) runs a function on each 1-D slice of the array along the given axis — useful when the function you need isn't already a built-in NumPy operation.
import numpy as np
arr = np.array([[1, 2, 3],
[4, 5, 6]])
row_sums = np.apply_along_axis(np.sum, 1, arr)
print(row_sums) # [ 6 15]
2. np.vectorize(func) wraps an ordinary Python function so it can be applied element-wise to an array, mainly for convenience rather than speed — it's essentially a thin loop under the hood, not a true C-level ufunc, so it's slower than a real vectorized operation for large arrays.
def double_if_even(x):
return x * 2 if x % 2 == 0 else x
vectorized_fn = np.vectorize(double_if_even)
print(vectorized_fn(np.array([1, 2, 3, 4]))) # [1 4 3 8]
60. What is the difference between shape and size attributes of NumPy array.
The shape and size attributes describe the dimensions of a NumPy array. shape returns the dimensions of the array (number of rows, columns, etc.), whereas size returns the total number of elements in the array.
shape
- Returns the dimensions of the array as a tuple.
- Indicates the number of elements along each axis.
- Useful for understanding the array's structure.
- Goal: Determine the dimensions of the array.
size
- Returns the total number of elements in the array.
- Calculated as the product of all dimensions.
- Returns a single integer.
- Goal: Determine how many elements the array contains.
61. What is difference between python sequences, pandas array and numpy array?
Python sequences, Pandas arrays, and NumPy arrays are all used to store and manipulate data, but they differ in their purpose and performance.
- General-purpose data structures such as lists and tuples.
- Can store different data types in the same sequence.
- Support basic operations like indexing, slicing, and iteration.
- Slower for numerical computations.
- Goal: Store and manipulate general-purpose data.
- Designed for numerical and scientific computing.
- Usually store elements of the same data type.
- Support fast vectorized operations and mathematical functions.
- Memory-efficient and high-performance.
- Goal: Efficient numerical computation.
Pandas Arrays (Series/DataFrame)
- Built on top of NumPy arrays.
- Support labeled rows and columns.
- Handle missing values and heterogeneous data efficiently.
- Provide powerful data manipulation, aggregation, and analysis features.
- Goal: Data cleaning, analysis, and tabular data processing.
62. How would you convert a pandas dataframe into NumPy array.
You can use the DataFrame's .values attribute to convert a Pandas DataFrame into a NumPy array.
import pandas as pd
import numpy as np
# Create a Pandas DataFrame (replace this with your actual DataFrame)
data = {'A': [1, 2, 3], 'B': [4, 5, 6]}
df = pd.DataFrame(data)
# Convert the DataFrame to a NumPy array
numpy_array = df.values
print(numpy_array)
Output:
[[1 4]
[2 5]
[3 6]]
63. How do you save and load NumPy arrays to/from disk?
NumPy provides its own fast binary format for persisting arrays, separate from generic text formats like CSV:
import numpy as np
arr = np.array([1, 2, 3])
np.save('my_array.npy', arr)
loaded = np.load('my_array.npy')
print(loaded) # [1 2 3]
- .npy/.npz files are much faster to read/write than CSV and preserve dtype and shape exactly.
64. How would you reverse a numpy array?
We can reverse a NumPy array using the [::-1] slicing technique.
import numpy as np
# Create a NumPy array (replace this with your array)
original_array = np.array([1, 2, 3, 4, 5])
# Reverse the array
reversed_array = original_array[::-1]
print(reversed_array)
Output:
[5 4 3 2 1]
65. Why NumPy is faster than list?
NumPy arrays are much faster than Python lists because of the way they are implemented:
- Homogeneous Data: NumPy arrays store elements of the same data type, unlike lists that can store mixed types. This allows NumPy to use fixed-size memory blocks.
- Contiguous Memory Allocation: NumPy stores data in continuous blocks of memory making element access and operations faster due to better CPU cache utilization.
- Vectorization: Operations in NumPy are implemented in C and use vectorized code, so computations are applied to the whole array at once instead of looping in Python.
- Low-Level Optimizations: NumPy relies on optimized C and Fortran libraries (like BLAS, LAPACK) which are much faster than Python’s built-in loops.
import numpy as np
import time
# Using Python list
py_list = list(range(1, 1000000))
start = time.time()
py_result = [x * 2 for x in py_list]
end = time.time()
print("Python List Time:", end - start)
# Using NumPy array
np_array = np.arange(1, 1000000)
start = time.time()
np_result = np_array * 2
end = time.time()
print("NumPy Array Time:", end - start)
Output:
Python List Time: 0.05335259437561035
NumPy Array Time: 0.004484653472900391
66. What is the procedure to count the number of times a given value appears in an array of integers?
The bincount() function can be used to count the instances of a given value. It should be noted that the bincount() function takes boolean expressions or positive integers as arguments. Integers that are negative cannot be used.
arr = NumPy.array([0, 5, 4, 0, 4, 4, 3, 0, 0, 5, 2, 1, 1, 9])
NumPy.bincount(arr)
67. How can you find the maximum or minimum value of an array in NumPy?
Using the max and min functions, we can determine array's maximum or minimum value in NumPy. These operations accept an array as an input and output the array's maximum or minimum value.
import numpy as np
# Create an array
arr = np.array([3, 2, 1])
# Find the maximum value of the array
max_value = np.max(arr)
# Find the minimum value of the array
min_value = np.min(arr)
# Print the maximum and minimum values
print("max value: ",max_value)
print("min value: ",min_value)
Output:
max value: 3
min value: 1
68. How do you find the index of the maximum/minimum value in an array?
While np.max()/np.min() return the value, np.argmax()/np.argmin() return the index (position) of that value — very commonly asked as a direct follow-up to the previous question.
import numpy as np
arr = np.array([3, 7, 1, 9, 4])
print(np.argmax(arr)) # 3 (index of the value 9)
print(np.argmin(arr)) # 2 (index of the value 1)
69. What is the difference between np.cumsum() and np.cumprod()?
Both compute running/cumulative results across an array, keeping every intermediate step, rather than returning a single reduced value like np.sum()/np.prod():
- np.cumsum(arr): running (cumulative) sum at each position.
- np.cumprod(arr): running (cumulative) product at each position.
70. How slicing and indexing can be used for data cleaning?
- Both indexing and slicing are useful methods for cleaning data because they let you modify or filter data based on particular criteria or target particular data points for modification.
- In this example, negative values are located and replaced with zeros using indexing and a new array with more than two members is created using slicing.
import numpy as np
# Sample NumPy array
data = np.array([1, 2, -1, 4, 5, -2, 7])
# Indexing: Replace negative values with zeros
data[data < 0] = 0
print("After replacing negatives with zeros:", data)
# Slicing: Extract elements greater than 2
subset = data[data > 2]
print("Subset with elements greater than 2:", subset)
Output:
After replacing negatives with zeros: [1 2 0 4 5 0 7]
Subset with elements greater than 2: [4 5 7]
71. How do you perform set operations (union, intersection, difference) on NumPy arrays?
NumPy provides a small suite of set-theory functions that work directly on arrays, treating them as sets of unique values:
- np.union1d(a, b): All unique values present in either array.
- np.intersect1d(a, b): Values present in both arrays.
- np.setdiff1d(a, b): Values in a that are not in b.
- np.isin(a, b): Boolean array — for each element of a, whether it exists in b.
import numpy as np
a = np.array([1, 2, 3, 4])
b = np.array([3, 4, 5, 6])
print(np.union1d(a, b)) # [1 2 3 4 5 6]
print(np.intersect1d(a, b)) # [3 4]
print(np.setdiff1d(a, b)) # [1 2]
print(np.isin(a, b)) # [False False True True]
72. How can you find the unique elements in an array in NumPy?
Apply the unique function from the NumPy module to identify the unique elements in an array in NumPy. This function returns the array's unique elements in sorted order.
import numpy as np
array = np.array([1, 2, 3, 1, 2, 3, 3, 4, 5, 6, 7, 5])
unique = np.unique(array)
print(unique)
Output:
[1 2 3 4 5 6 7]