[PYTHON] About assignment of numpy.ndarray

I was addicted to the assignment of numpy.ndarray, so make a note

If you write in three lines

--About slices and masks of np.ndarray. --If you use it simply, you can use it in the same way when you assign it to the original object. --Slice returns view, but mask (fancy index) returns copy, so be careful when chaining or doing complicated things.

ndarray slices and masks

As you know, ndarray can be assigned to the range specified by slice.

slice.py


In [1]: import numpy as np

In [2]: table = np.zeros((2, 5))

In [3]: table[1, :3] = 1

In [4]: table
Out[4]:
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 1.,  1.,  1.,  0.,  0.]])

This is because ndarray returns reference instead of copy when specified in slices.

You can also do the same with a Boolean mask.

mask.py


In [1]: import numpy as np

In [2]: table = np.zeros((2, 5))

In [3]: table[1, [True, True, True, False, False]] = 1

In [4]: table
Out[4]:
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 1.,  1.,  1.,  0.,  0.]])

it's the same.

Addictive point: ndarray slice and mask chain

Let's chain this.

chain1.py


In [1]: import numpy as np

In [2]: table = np.zeros((2, 5))

In [3]: table[1, :3][1:] = 1

In [4]: table
Out[4]:
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  1.,  1.,  0.,  0.]])

Since the slice returns Reference, the Reference of Reference is Reference, so we were able to safely assign it to the original table. It's easy. Now let's do the same for masks.

chain2.py


In [1]: import numpy as np

In [2]: table = np.zeros((2, 5))

In [3]: table[1, [True, True, True, False, False]][[False, True, True]] = 1

In [4]: table  #Not assigned!!!!
Out[4]:
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.]])

Well, I got a different result than I expected.

chain3.py


In [1]: import numpy as np

In [2]: table = np.zeros((2, 5))

In [3]: table[1, [True, True, True, False, False]][1:] = 1

In [4]: table  #Not assigned!!!!
Out[4]:
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.]])

The same applies to the mask + slice chain.

What do you mean ...

Cause and description

There is a detailed explanation in the official documentation. http://scipy-cookbook.readthedocs.io/items/ViewsVsCopies.html

But fancy indexing does seem to return views sometimes, doesn't it? If you check the section of

sample1.py


>>> a = numpy.arange(10)
>>> a[[1,2]] = 100
>>> a
array([  0, 100, 100,   3,   4,   5,   6,   7,   8,   9])

When

sample2.py


>>> a = numpy.arange(10)
>>> c1 = a[[1,2]]
>>> c1[:] = 100
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> c1
array([100, 100])

Explains the difference. This pattern is also this time.

In conclusion, The mask (fancy index) did not actually return a view.

The mask was able to overwrite the original object not because it was returning a view, but because the python interpreter was converting it to an inplace expression.

fancy_index1.py


>>> a[[1,2]] = 100

Is

fancy_index1_translated.py


a.__setitem__([1,2], 100)

It means that the original value of a has changed because it is converted to. However,

fancy_index2.py


c1 = a[[1,2]]

Is

fancy_index2_translated.py


c1 = a.__getitem__([1,2])

And view, not copy, so the result will change the moment you divide it into two lines.

By applying this, the results of chain2.py and chain3.py can also be explained.

table[1, [True, True, True, False, False]]

Returns a copy, so no matter how much you overwrite it after that, the original table will not be changed.

Finally the problem

chain4.py


In [1]: import numpy as np

In [2]: table = np.zeros((2, 5))

In [3]: table[1, :3][False, True, True] = 1

In [4]: table
Out[4]: ???

What result does this return ??

Recommended Posts

About assignment of numpy.ndarray
About all of numpy
About MultiIndex of pandas
About variable of chainer
About cumulative assignment of lists and numpy arrays
About max_iter of LogisticRegression () of scikit-learn
About Japanese path of pyminizip
About the ease of Python
About Japanese support of cometchat
About various encodings of Python 3
About all of numpy (2nd)
About cost calculation of MeCab
About approximate fractions of pi
About the components of Luigi
About HOG output of Scikit-Image
About the features of Python
About data management of anvil-app-server
About the return value of pthread_mutex_init ()
About the return value of the histogram.
About the basic type of Go
About the upper limit of threads-max
About circular crossover of genetic algorithms
About the behavior of yield_per of SqlAlchemy
About import error of PyQt5.QtWidgets (Anaconda)
About the size of matplotlib points
About color halftone processing of images
About the basics list of Python basics
About building GUI using TKinter of Python
About the behavior of enable_backprop of Chainer v2
About the virtual environment of python version 3.7
About sensor_mode and angle of view of picamera
Memorandum of python beginners About inclusion notation
A memorandum of understanding about django's QueryDict
About the arguments of the setup function of PyCaret
About Japanese fonts of matplotlib (for Mac)
About the Normal Equation of Linear Regression
Memo of troubles about coexistence of Python 2/3 system
[Python] Chapter 02-04 Basics of Python Program (About Comments)