1

The question sounds very basic. But when I try to use where or boolean conditions on numpy arrays, it always returns a flattened array.

I have the NumPy array

P = array([[ 0.49530662,  0.07901   , -0.19012371],
       [ 0.1421513 ,  0.48607405, -0.20315014],
       [ 0.76467375,  0.16479826, -0.56598029],
       [ 0.53530718, -0.21166188, -0.08773241]])

I want to extract the array of only negative values, but when I try

P[P<0]
array([-0.19012371, -0.41421612, -0.20315014, -0.56598029, -0.21166188,
       -0.08773241, -0.09241335])
P[np.where(P<0)]
array([-0.19012371, -0.41421612, -0.20315014, -0.56598029, -0.21166188,
       -0.08773241, -0.09241335])

I get a flattened array. How can I extract the array of the form

array([[ 0,  0,          -0.19012371],
       [ 0 , 0,          -0.20315014],
       [ 0,  0,          -0.56598029],
       [ 0, -0.21166188, -0.08773241]])

I do not wish to create a temp array and then use something like Temp[Temp>=0] = 0

Georgy
  • 12,464
  • 7
  • 65
  • 73
Shew
  • 1,557
  • 1
  • 21
  • 36
  • You cannot do that. Reason for that is very simple: NumPy will try to return you what you are asking for, which is all negative values. However, if you want to keep the dimensions, then it would be an array which has an inconsistent dimension length. Therefore, the only way to get to the answer you want, is using the code you are already suggesting. – 1313e May 02 '19 at 07:39
  • Just get indexes of all elements above 0 and set them 0! Check my answer below @Shew – Devesh Kumar Singh May 02 '19 at 07:47
  • The OP wants to extract the array, not convert the existing one. – 1313e May 02 '19 at 08:03
  • Yes, another poster already pointed that out, and I have changed my answer accordingly, please take a look @1313e and consider upvoting if possible :) – Devesh Kumar Singh May 02 '19 at 08:08
  • Next time I suggest you to compose Question with correct output and in general well thought. Also I suggest you to write EDIT when you edit question. Your previous question didnt make sense, but after your edit, it starts to make sense. However my answer now doesnt make sense since you edited your question – Martin May 02 '19 at 08:15

2 Answers2

3

Since your need is:

I want to "extract" the array of only negative values

You can use numpy.where() with your condition (checking for negative values), which can preserve the dimension of the array, as in the below example:

In [61]: np.where(P<0, P, 0)
Out[61]: 
array([[ 0.        ,  0.        , -0.19012371],
       [ 0.        ,  0.        , -0.20315014],
       [ 0.        ,  0.        , -0.56598029],
       [ 0.        , -0.21166188, -0.08773241]])

where P is your input array.


Another idea could be to use numpy.zeros_like() for initializing a same shape array and numpy.where() to gather the indices at which our condition satisfies.

# initialize our result array with zeros
In [106]: non_positives = np.zeros_like(P)

# gather the indices where our condition is obeyed
In [107]: idxs = np.where(P < 0)

# copy the negative values to correct indices
In [108]: non_positives[idxs] = P[idxs]

In [109]: non_positives
Out[109]: 
array([[ 0.        ,  0.        , -0.19012371],
       [ 0.        ,  0.        , -0.20315014],
       [ 0.        ,  0.        , -0.56598029],
       [ 0.        , -0.21166188, -0.08773241]])

Yet another idea would be to simply use the barebones numpy.clip() API, which would return a new array, if we omit the out= kwarg.

In [22]: np.clip(P, -np.inf, 0)    # P.clip(-np.inf, 0)
Out[22]: 
array([[ 0.        ,  0.        , -0.19012371],
       [ 0.        ,  0.        , -0.20315014],
       [ 0.        ,  0.        , -0.56598029],
       [ 0.        , -0.21166188, -0.08773241]])
kmario23
  • 57,311
  • 13
  • 161
  • 150
0

This should work, essentially get the indexes of all elements which are above 0, and set them to 0, this will preserve the dimensions! I got the idea from here: Replace all elements of Python NumPy Array that are greater than some value

Also note that I have modified the original array, I haven't used a temp array here

import numpy as np

P = np.array([[ 0.49530662,  0.07901   , -0.19012371],
       [ 0.1421513 ,  0.48607405, -0.20315014],
       [ 0.76467375,  0.16479826, -0.56598029],
       [ 0.53530718, -0.21166188, -0.08773241]])

P[P >= 0] = 0
print(P)

The output will be

[[ 0.          0.         -0.19012371]
 [ 0.          0.         -0.20315014]
 [ 0.          0.         -0.56598029]
 [ 0.         -0.21166188 -0.08773241]]

As noted below, this will modify the array, so we should use np.where(P<0, P 0) to preserve the original array as follows, thanks @kmario123 as follows

import numpy as np

P = np.array([[ 0.49530662,  0.07901   , -0.19012371],
       [ 0.1421513 ,  0.48607405, -0.20315014],
       [ 0.76467375,  0.16479826, -0.56598029],
       [ 0.53530718, -0.21166188, -0.08773241]])

print( np.where(P<0, P, 0))
print(P)

The output will be

[[ 0.          0.         -0.19012371]
 [ 0.          0.         -0.20315014]
 [ 0.          0.         -0.56598029]
 [ 0.         -0.21166188 -0.08773241]]
[[ 0.49530662  0.07901    -0.19012371]
 [ 0.1421513   0.48607405 -0.20315014]
 [ 0.76467375  0.16479826 -0.56598029]
 [ 0.53530718 -0.21166188 -0.08773241]]
Devesh Kumar Singh
  • 20,259
  • 5
  • 21
  • 40
  • Please note that this will modify the original array, forever. – kmario23 May 02 '19 at 08:00
  • Thanks for the observation, I have updated the answer and mentioned the caveat in the old answer, and also mentioned you in the updated way, please check if it looks good @kmario23 and upvote if possible :) – Devesh Kumar Singh May 02 '19 at 08:08