Indexing returns views not copies in NumPy - Time & Space Complexity
When we use indexing in numpy, it often gives us a view of the data, not a full copy.
We want to see how this affects the time it takes to access or change data.
Analyze the time complexity of the following code snippet.
import numpy as np
arr = np.arange(1000000)
sub_arr = arr[1000:2000]
sub_arr[0] = 999
This code creates a large array, then takes a slice which is a view, and changes one element in the slice.
- Primary operation: Slice indexing (view creation) and element assignment
- How many times: Once each (constant time)
When we take a slice, numpy does not copy data but creates a view in constant time.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | Constant (~5 operations) |
| 100 | Constant (~5 operations) |
| 1000 | Constant (~5 operations) |
Pattern observation: The time to create a view is constant O(1), independent of slice size, no data copying happens.
Time Complexity: O(1)
This means the time is constant regardless of the size of the slice (k), with no copying cost.
[X] Wrong: "Indexing always makes a full copy of the data, so it takes a long time."
[OK] Correct: Actually, numpy usually creates a view, which is fast and shares data with the original array.
Knowing when numpy makes views or copies helps you write faster code and answer questions about data handling clearly.
"What if we used fancy indexing (like a list of indices) instead of a slice? How would the time complexity change?"
Practice
arr[1:4]?Solution
Step 1: Understand NumPy slicing behavior
In NumPy, slicing an array returns a view, not a copy. This means the new array shares the same data buffer as the original.Step 2: Consequence of view sharing data
Because the slice is a view, changes to it will affect the original array, confirming it is not an independent copy.Final Answer:
It returns a view that shares data with the original array. -> Option AQuick Check:
Indexing slice = view sharing data [OK]
- Thinking slicing creates a copy
- Confusing views with copies
- Assuming slicing returns a list
Solution
Step 1: Identify method to create independent copy
The.copy()method creates a new array with its own data, independent of the original.Step 2: Check syntax correctness
Onlyarr[2:5].copy()correctly callscopy()on the slice. Other options either miss parentheses or use wrong methods.Final Answer:
slice = arr[2:5].copy() -> Option CQuick Check:
Use .copy() for independent array [OK]
- Forgetting parentheses on .copy()
- Using .view() instead of .copy()
- Assuming slicing alone makes a copy
import numpy as np arr = np.array([10, 20, 30, 40, 50]) slice_arr = arr[1:4] slice_arr[0] = 99 print(arr)
What is the output?
Solution
Step 1: Understand slice is a view
The slicearr[1:4]returns a view sharing data witharr. Changingslice_arr[0]changesarr[1].Step 2: Apply the change and print
Settingslice_arr[0] = 99updatesarr[1]to 99. The rest ofarrremains unchanged.Final Answer:
[10 99 30 40 50] -> Option AQuick Check:
View change updates original array [OK]
- Expecting original array unchanged
- Changing wrong indices
- Confusing slice indices with original
import numpy as np arr = np.array([1, 2, 3, 4, 5]) slice_arr = arr[1:4] slice_arr = slice_arr + 10 print(arr)
Why does
arr remain unchanged?Solution
Step 1: Analyze the operation
This operation creates a new array with values increased by 10. It does not modifyslice_arr + 10slice_arrin place.Step 2: Understand assignment effect
Assigningslice_arr = slice_arr + 10makesslice_arrpoint to a new array. The originalarrremains unchanged because no in-place modification happened.Final Answer:
Becauseslice_arr + 10creates a new array, not modifying the view. -> Option BQuick Check:
slice + scalar creates new array, no original change [OK]
- Assuming slice_arr + 10 modifies original array
- Thinking slicing always copies
- Believing arrays are immutable
data and want to modify a slice without affecting the original array. Which approach is best to ensure safety and memory efficiency?Solution
Step 1: Understand views vs copies for safety
Modifying a view changes the original array. To avoid this, a copy is needed.Step 2: Consider memory efficiency
Copying only the needed slice with.copy()uses less memory than copying the whole array and ensures safe modification.Step 3: Evaluate other options
Usingslice = data[100:200]and modifyingslicedirectly modifies the original data unintentionally. Usingslice = data[100:200].view()and modifyingslicecreates a view, which is not safe. Modifyingdatadirectly without slicing affects the entire array, not just the slice.Final Answer:
Useslice = data[100:200].copy()to modify safely without changingdata. -> Option DQuick Check:
Copy slice for safe, efficient modification [OK]
- Modifying views thinking they are copies
- Copying entire array unnecessarily
- Ignoring memory use in large arrays
Ready to prove it?
Pass the test and this pattern moves unknown
