Reputation: 615
I have a numpy array of different numpy arrays and I want to make a deep copy of the arrays. I found out the following:
import numpy as np
pairs = [(2, 3), (3, 4), (4, 5)]
array_of_arrays = np.array([np.arange(a*b).reshape(a,b) for (a, b) in pairs])
a = array_of_arrays[:] # Does not work
b = array_of_arrays[:][:] # Does not work
c = np.array(array_of_arrays, copy=True) # Does not work
d = np.array([np.array(x, copy=True) for x in array_of_arrays])
array_of_arrays[0][0,0] = 100
print a[0][0,0], b[0][0,0], c[0][0,0], d[0][0,0]
Is d the best way to do this? Is there a deep copy function I missed? And what is the best way to interact with each element in this array of different sized arrays?
Upvotes: 31
Views: 80292
Reputation: 313
Yes, you can make a deep copy of a NumPy array using the numpy.copy() function. You can find the documentation for this function here.
The documentation provides an example of how to use the function:
import numpy as np
# Create an array x, with a reference y and a copy z:
x = np.array([1, 2, 3])
y = x
z = np.copy(x)
# Modify x and check if y and z are affected:
x[0] = 10
print(x[0] == y[0]) # True
print(x[0] == z[0]) # False
You can also copy an array using the following methods:
x = np.array([[1,2,3],[4,5,6]], order='F')
y = x.copy()
x.fill(0)
print(x == y) # [[False False False]
# [False False False]]
You can find the documentation for this method here.
Upvotes: 0
Reputation: 932
Just use np.array(old_array)
should work for the latest version of numpy
array_to_be_copy = np.zeros([3, 3])
deep_copied_array = np.array(array_to_be_copy)
My numpy version: 1.21.1
Upvotes: 7
Reputation: 1
When to warn of possible depreciation:
I decided like that:
import numpy as np import copy def deepCopyArrayNumPy(arrayNunpy): clone = copy.deepcopy(arrayNunpy.tolist()) return np.array(clone)
Upvotes: 0
Reputation: 1
A simple np.asarray() would do it
np.asarray(array_of_arrays)
For reference: https://numpy.org/doc/stable/reference/generated/numpy.asarray.html
Upvotes: -1
Reputation: 231540
In [276]: array_of_arrays
Out[276]:
array([array([[0, 1, 2],
[3, 4, 5]]),
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]]),
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])], dtype=object)
array_of_arrays
is dtype=object
; that means each element of the array is a pointer to an object else where in memory. In this case those elements are arrays of different sizes.
a = array_of_arrays[:]
a
is a new array, but a view of array_of_arrays
; that is, it has the same data buffer (which in this case is list of pointers).
b = array_of_arrays[:][:]
this is just a view of a view. The second [:]
acts on the result of the first.
c = np.array(array_of_arrays, copy=True)
This is the same as array_of_arrays.copy()
. c
has a new data buffer, a copy of the originals
If I replace an element of c
, it will not affect array_of_arrays
:
c[0] = np.arange(3)
But if I modify an element of c
, it will modify the same element in array_of_arrays
- because they both point to the same array.
The same sort of thing applies to nested lists of lists. What array
adds is the view
case.
d = np.array([np.array(x, copy=True) for x in array_of_arrays])
In this case you are making copies of the individual elements. As others noted there is a deepcopy
function. It was designed for things like lists of lists, but works on arrays as well. It is basically doing what you do with d
; recursively working down the nesting tree.
In general, an object array is like list nesting. A few operations cross the object boundary, e.g.
array_of_arrays+1
but even this effectively is
np.array([x+1 for x in array_of_arrays])
One thing that a object array adds, compared to a list, is operations like reshape
. array_of_arrays.reshape(3,1)
makes it 2d; if it had 4 elements you could do array_of_arrays.reshape(2,2)
. Some times that's handy; other times it's a pain (it's harder to iterate).
Upvotes: 5
Reputation: 1375
Beaten by one minute. Indeed, deepcopy is the answer here.
To your second question abut indexing: I have a feeling that you may be better off with a simple list or a dictionary-type data structure here. np.arrays make sense primarily if each array element is of the same type. Of course you can argue that each element in array_of_arrays is another array, but what is the benefit of having them collected in a numpy array instead of a simple list?
list_of_arrays = [np.arange(a*b).reshape(a,b) for (a, b) in pairs]
Upvotes: 4
Reputation: 1367
import numpy as np
import copy
pairs = [(2, 3), (3, 4), (4, 5)]
array_of_arrays = np.array([np.arange(a*b).reshape(a,b) for (a, b) in pairs])
a = copy.deepcopy(array_of_arrays)
Feel free to read up more about this here.
Oh, here is simplest test case:
a[0][0,0]
print a[0][0,0], array_of_arrays[0][0,0]
Upvotes: 32