tanay
tanay

Reputation: 458

How to delete decimal values from an array in a pythonic way

I am trying to delete an element from an array. When trying to delete integer values(using numpy.delete) it's working but it doesn't work for decimal values.

For integer deletion

X = [1.  2.  2.5 5.7 3. 6. ]
to_delete_key = [3, 7.3]
Y = np.delete(X, to_delete_key, None)
Output is [1.  2.  2.5 5.7 6. ]
The value 3 got deleted

Whereas in the case of decimal deletion

 For decimal deletion
X = [6.  7.3 9.1]
to_delete_key = [3, 7.3]
Y = np.delete(X, to_delete_key, None)
Output is [6.  7.3 9.1]
The value 7.3 didn't get deleted.

I know how to do it the normal way but is there any efficient pythonic way to do it

Upvotes: 0

Views: 454

Answers (2)

Tarik
Tarik

Reputation: 11209

You are dealing with floating-point numbers that cannot be compared exactly. Google out "What every programmer should know about floating-point numbers".
1/3 + 1/3 + 1/3 might not be equal to 1 due to rounding errors.

So the explanation is that your value of 7.3 is not found. Numpy probably converted 7.3 to a 32-bit float or whatever that is not exactly equal to what is in the array.

As mentioned by @elPastor, you are misusing Numpy.

Upvotes: 0

hpaulj
hpaulj

Reputation: 231540

In [249]: X = np.array([1.,  2.,  2.5, 5.7, 3., 6. ])
     ...: to_delete_key = [3, 7.3]

In [252]: np.delete(X, to_delete_key)
Traceback (most recent call last):
  File "<ipython-input-252-f9031065a548>", line 1, in <module>
    np.delete(X, to_delete_key)
  File "<__array_function__ internals>", line 5, in delete
  File "/usr/local/lib/python3.8/dist-packages/numpy/lib/function_base.py", line 4406, in delete
    keep[obj,] = False
IndexError: arrays used as indices must be of integer (or boolean) type

Using an integer:

In [253]: np.delete(X, 3)
Out[253]: array([1. , 2. , 2.5, 3. , 6. ])

It was the 5.7 that was deleted, X[3].

np.delete does not delete by value! From the docs:

obj : slice, int or array of ints
    Indicate indices of sub-arrays to remove along the specified axis.

We can look for value matches

In [267]: vals = [3, 2.5]
In [268]: X[:,None]==vals
Out[268]: 
array([[False, False],
       [False, False],
       [False,  True],
       [False, False],
       [ True, False],
       [False, False]])

But equality match on floats can be unreliable. isclose operates with a tolerance:

In [269]: np.isclose(X[:,None],vals)
Out[269]: 
array([[False, False],
       [False, False],
       [False,  True],
       [False, False],
       [ True, False],
       [False, False]])

Then find the rows where there's a match:

In [270]: _.any(axis=1)
Out[270]: array([False, False,  True, False,  True, False])
In [271]: X[_]
Out[271]: array([2.5, 3. ])
In [272]: X[~__]
Out[272]: array([1. , 2. , 5.7, 6. ])

Lists have a remove by value:

In [284]: alist=X.tolist()
In [285]: alist.remove(3.0)
In [286]: alist.remove(2.5)
In [287]: alist
Out[287]: [1.0, 2.0, 5.7, 6.0]

Upvotes: 1

Related Questions