33

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?

2
  • 2
    You really should expand on the 'does not work' lines. Commented Jun 2, 2016 at 14:39
  • I tested using np.copy (which should be the same as adding copy=True) and the problem is that it is actually a copy by reference! (So a change in the original reflected in the copy, for some reason). np.copy or copy=True works well for normal arrays, though. Commented Aug 14, 2020 at 9:57

7 Answers 7

33
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]
Sign up to request clarification or add additional context in comments.

3 Comments

Nice test case!
>>> np.array([np.arange(ab).reshape(a,b) for (a, b) in pairs]) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (3,) + inhomogeneous part. (Python 3.8.10, Numpy 1.24.2.) But this works as expected: >>> ([np.arange(ab).reshape(a,b) for (a, b) in pairs])
"a[0][0,0]": shouldn't this read "a[0][0,0] = 99" or "array_of_arrays[0][0,0] = 100" the like? Otherwise the following are identical: print a[0][0,0], array_of_arrays[0][0,0]
6

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

Comments

5
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).

Comments

4

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]

Comments

0

When to warn of possible depreciation:

  1. ..\lib\site-packages\ipykernel_launcher.py:23: DeprecationWarning: elementwise comparison failed; this will raise an error in the future.

I decided like that:

    import numpy as np
    import copy
    
    def deepCopyArrayNumPy(arrayNunpy):
        clone = copy.deepcopy(arrayNunpy.tolist())
        return np.array(clone)

1 Comment

Thanks for this answer, but can you explain why it is better than the accepted answer using deepcopy directly?
0

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.

Comments

-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

1 Comment

It will not do a deep copy. Python 3.7.4 (default, Aug 13 2019, 20:35:49) [GCC 7.3.0] :: Anaconda, Inc. on linux Type "help", "copyright", "credits" or "license" for more information. >>> import numpy as np >>> a = np.zeros((3,3)) >>> a array([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]) >>> b = np.asarray(a) >>> b array([[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]) >>> a[0,0] = 1 >>> a array([[1., 0., 0.], [0., 0., 0.], [0., 0., 0.]]) >>> b array([[1., 0., 0.], [0., 0., 0.], [0., 0., 0.]]) >>>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.