Replace values in specific columns of a numpy arra

2019-08-27 00:20发布

I have a N x M numpy array (matrix). Here is an example with a 3 x 5 array:

x = numpy.array([[0,1,2,3,4,5],[0,-1,2,3,-4,-5],[0,-1,-2,-3,4,5]])

I'd like to scan all the columns of x and replace the values of each column if they are equal to a specific value. This code for example aims to replace all the negative values (where the value is equal to the column number) to 100:

for i in range(1,6):
    x[:,i == -(i)] = 100 

This code obtains this warning:

DeprecationWarning: using a boolean instead of an integer will result in an error in the future

I'm using numpy 1.8.2. How can I avoid this warning without downgrade numpy?

4条回答
smile是对你的礼貌
2楼-- · 2019-08-27 00:38

As others have said, your loop isn't doing what you think it is doing. I would propose you change your code to use numpy's fancy indexing.

# First, create the "test values" (column index):
>>> test_values = numpy.arange(6)
# test_values is array([0, 1, 2, 3, 4, 5])
#
# Now, we want to check which columns have value == -test_values:
#
>>> mask = (x == -test_values) & (x < 0)
# mask is True wherever a value in the i-th column of x is negative i
>>> mask
array([[False, False, False, False, False, False],
       [False,  True, False, False,  True,  True],
       [False,  True,  True,  True, False, False]], dtype=bool)
#
# Now, set those values to 100
>>> x[mask] = 100
>>> x
array([[  0,   1,   2,   3,   4,   5],
       [  0, 100,   2,   3, 100, 100],
       [  0, 100, 100, 100,   4,   5]])
查看更多
Lonely孤独者°
3楼-- · 2019-08-27 00:53

Even without the warning, the code you have there will not do what you want. i is the loop index and will equal minus itself only if i == 0, which is never. Your test will always return false, which is cast to 0. In other words your code will replace the first element of each row with 100.

To get this to work I would do

for i in range(1, 6):
    col = x[:,i]
    col[col == -i] = 100

Notice that you use the name of the array for the masking and that you need to separate the conventional indexing from the masking

查看更多
Melony?
4楼-- · 2019-08-27 01:02

If you are worried about the warning spewing out text, then ignore it as a Warning/Exception:

import numpy
import warnings


warnings.simplefilter('default')  # this enables DeprecationWarnings to be thrown


x = numpy.array([[0,1,2,3,4,5],[0,-1,2,3,-4,-5],[0,-1,-2,-3,4,5]])

with warnings.catch_warnings():
    warnings.simplefilter("ignore")  # and this ignores them
    for i in range(1,6):
        x[:,i == -(i)] = 100
print(x)  # just to show that you are actually changing the content

As you can see in the comments, some people are not getting DeprecationWarning. That is probably because python suppresses developer-only warnings since 2.7

查看更多
ら.Afraid
5楼-- · 2019-08-27 01:04

I don't follow what your code is trying to do:

the i == -(i)

will evaluate to something like this:

x[:, True]
x[:, False]

I don't think this is what you want. You should try something like this:

for i in range(1, 6):
    mask = x[:, i] == -i
    x[:, i][mask] = 100

Create a mask over the whole column, and use that to change the values.

查看更多
登录 后发表回答