NumPy Copies and Views
A copy is a complete duplicate of the data. If we modify the copy, it does not affect the original data, and the physical memory locations are different.
A view is an alias or reference to the data, allowing access and manipulation of the original data without creating a copy. If we modify the view, it affects the original data, and the physical memory locations are the same.
Views typically occur when:
- Slicing operations in NumPy return views of the original data.
- Calling the
view()
function of an ndarray creates a view.
- Calling the
Copies typically occur when:
- Slicing operations in Python sequences, calling the
deepCopy()
function. - Calling the
copy()
function of an ndarray creates a copy.
No Copy
Simple assignment does not create a copy of the array object. Instead, it uses the same id()
to access the original array. The id()
returns a universal identifier for a Python object, similar to a pointer in C.
Additionally, any changes to one array are reflected in the other. For example, changing the shape of one array also changes the shape of the other.
Example
import numpy as np
a = np.arange(6)
print('Our array is:')
print(a)
print('Calling id() function:')
print(id(a))
print('Assigning a to b:')
b = a
print(b)
print('b has the same id():')
print(id(b))
print('Modifying the shape of b:')
b.shape = 3, 2
print(b)
print('The shape of a is also modified:')
print(a)
Output:
Our array is:
[0 1 2 3 4 5]
Calling id() function:
4349302224
Assigning a to b:
[0 1 2 3 4 5]
b has the same id():
4349302224
Modifying the shape of b:
[[0 1]
[2 3]
[4 5]]
The shape of a is also modified:
[[0 1]
[2 3]
[4 5]]
View or Shallow Copy
The ndarray.view()
method creates a new array object, and changes to the dimensions of the new array do not affect the dimensions of the original data.
Example
import numpy as np
# Initially, a is a 3x2 array
a = np.arange(6).reshape(3, 2)
print('Array a:')
print(a)
print('Creating a view of a:')
b = a.view()
print(b)
print('The two arrays have different id():')
print('id() of a:')
print(id(a))
print('id() of b:')
print(id(b))
# Modifying the shape of b does not modify a
b.shape = 2, 3
print('Shape of b:')
print(b)
print('Shape of a:')
print(a)
Output:
Array a:
[[0 1]
[2 3]
[4 5]]
Creating a view of a:
[[0 1]
[2 3]
[4 5]]
The two arrays have different id():
id() of a:
4314786992
id() of b:
4315171296
Shape of b:
[[0 1 2]
[3 4 5]]
Shape of a:
[[0 1]
[2 3]
[4 5]]
Using slicing to create a view and modifying the data affects the original array:
Example
import numpy as np
arr = np.arange(12)
print('Our array:')
print(arr)
print('Creating a slice:')
a = arr[3:]
b = arr[3:]
a[1] = 123
b[2] = 234
print(arr)
print(id(a), id(b), id(arr[3:]))
Output:
Our array:
[ 0 1 2 3 4 5 6 7 8 9 10 11]
Creating a slice:
[ 0 1 2 3 123 234 6 7 8 9 10 11]
4545878416 4545878496 4545878576
Variables a and b are views of a part of arr, and modifications to the views directly reflect in the original data. However, observing the id
of a and b, they are different, indicating that while views point to the original data, they are distinct from assignment references.
Copy or Deep Copy
The ndarray.copy()
function creates a copy. Modifications to the copy do not affect the original data, and their physical memory locations are different.
Example
import numpy as np
a = np.array([[10, 10], [2, 3], [4, 5]])
print('Array a:')
print(a)
print('Creating a deep copy of a:')
b = a.copy()
print('Array b:')
print(b)
Output:
Array a:
[[10 10]
[ 2 3]
[ 4 5]]
Creating a deep copy of a:
Array b:
[[10 10]
[ 2 3]
[ 4 5]]
print(b)
# b does not share anything with a
print('Can we write to b to write to a?')
print(b is a)
print('Modify the contents of b:')
b[0,0] = 100
print('Array b after modification:')
print(b)
print('a remains unchanged:')
print(a)
Output result:
Array a:
[[10 10]
[ 2 3]
[ 4 5]]
Create a deep copy of a:
Array b:
[[10 10]
[ 2 3]
[ 4 5]]
Can we write to b to write to a?
False
Modify the contents of b:
Array b after modification:
[[100 10]
[ 2 3]
[ 4 5]]
a remains unchanged:
[[10 10]
[ 2 3]
[ 4 5]]
More related articles
Python Direct Assignment, Shallow Copy, and Deep Copy Explained