Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python arrays are automatically copying each other

Tags:

python

numpy

I am a beginner at python and I don't want these arrays to copy each other but they are automatically:

a = numpy.zeros(4)
b = a
a[1] = 10
print b[1]

and it returns 10 instead of 0. How do I disconnect these two arrays?

like image 890
Mark Aisenberg Avatar asked Sep 28 '22 05:09

Mark Aisenberg


2 Answers

"The arrays are automatically copying each other" is a false statement for several reasons. The primary reason is that you only have one array, and two variables names that refer to that array.

Here are three ways to copy a numpy array (i.e. create another array exactly like it):

>>> a = numpy.zeros(4)
>>> b = a.copy()
>>> c = numpy.copy(a)
>>> d = numpy.array(a)
>>> a[1] = 10
>>> a
array([  0.,  10.,   0.,   0.])
>>> b
array([ 0.,  0.,  0.,  0.])
>>> c
array([ 0.,  0.,  0.,  0.])
>>> d
array([ 0.,  0.,  0.,  0.])

Note that slice-copying (e.g. e = a[:]) will not work with numpy arrays.

like image 174
Shashank Avatar answered Oct 31 '22 00:10

Shashank


You need a copy:

b  = a.copy()

b = a creates a reference so a is b, they are both pointing to the same location in memory, a.copy() actually creates a new object.

In [5]: a = numpy.zeros(4)    
In [6]: b = a   # reference
In [7]: id(a)
Out[7]: 140335847505968    
In [8]: id(b)         # same id's 
Out[8]: 140335847505968    
In [9]: a is b
Out[9]: True    
In [10]: b = a.copy() # new object    
In [11]: id(a)
Out[11]: 140335847505968    
In [12]: id(b)   # # now  different id's
Out[12]: 140335437696176    
In [13]: a is b # b is no longer pointing to the same memory location
Out[13]: False

If you slice the array using basic slicing, the id's will differ but any changes will be reflected in both a and b as when using basic indexing All arrays generated by basic slicing are always views of the original array. A view is An array that does not own its data, but refers to another array’s data instead. So the view is a new object but the content still belongs to the original array.

However using advanced indexing Advanced indexing always returns a copy of the data

In [141]: a = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])   
In [142]: b = a[1:7:2]    # basic indexing/view
In [143]: id(a)
Out[143]: 140335437385856    
In [144]: id(b)      
Out[144]: 140335437356528    
In [145]: b[0] = 999    
In [146]: a
Out[146]: array([  0, 999,   2,   3,   4,   5,   6,   7,   8,   9])
In [148]: b
Out[148]: array([999,   3,   5])    
In [149]: a = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])    
In [150]: b = a[[0,3,5]]  # advanced indexing/copy  
In [151]: b
Out[151]: array([0, 3, 5])    
In [152]: b[0] = 999    
In [153]: a
Out[153]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])    
In [154]: b
Out[154]: array([999,   3,   5])
In [157]: a = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [158]: b = a[a]   # copy
In [159]: b
Out[159]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])    
In [160]: b[0] = 99    
In [161]: a
Out[161]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])    
In [162]: b
Out[162]: array([99,  1,  2,  3,  4,  5,  6,  7,  8,  9])

This is specific numpy behaviour, slicing a regular python flat list will always create a new list where changes in a will not be reflected in b.

In [190]: a = [1,2,3,4,5]

In [191]: b = a[:3]

In [192]: b[0] = 999

In [193]: a
Out[193]: [1, 2, 3, 4, 5]

In [194]: b
Out[194]: [999, 2, 3]

Where you will get caught with a python list is if the list contains sublists and you create a shallow copy:

In [197]: a = [[1,2,3],[4,5]]
In [198]: b = a[:]    
In [199]: id(a)
Out[199]: 140335437468296    
In [200]: id(b)
Out[200]: 140335437417992
In [201]: b[0][0] = 999 
In [202]: b
Out[202]: [[999, 2, 3], [4, 5]]   
In [203]: a
Out[203]: [[999, 2, 3], [4, 5]]

You would need to make a copy.deepcopy:

In [204]: a = [[1,2,3],[4,5]]    
In [205]: from copy import  deepcopy
In [206]: b = deepcopy(a)    
In [207]: b[0][0] = 999    
In [208]: b
Out[208]: [[999, 2, 3], [4, 5]]    
In [209]: a
Out[209]: [[1, 2, 3], [4, 5]]
like image 35
Padraic Cunningham Avatar answered Oct 31 '22 00:10

Padraic Cunningham