Dominik Müller
Dominik Müller

Reputation: 615

Deep copy of a np.array of np.array

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

Answers (7)

roei shlezinger
roei shlezinger

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

Jerry wu
Jerry wu

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

Fabio Santos
Fabio Santos

Reputation: 1

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)

Upvotes: 0

Aditya Bhadoo
Aditya Bhadoo

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

hpaulj
hpaulj

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

maschu
maschu

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

Tomasz Plaskota
Tomasz Plaskota

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

Related Questions