29

Is there any built in function to discard integer and keep only float number in numpy.

import numpy as np

input = np.array([0.0, 0.01, 1.0, 2.0, 2.001, 2.002])

desired_ouput = some_function(input)
# Expected ouput
# desired_output = np.array([0.01, 2.001, 2.002])
Oli
  • 1,313
  • 14
  • 31

7 Answers7

18

I don't think so. My approach would be

import numpy as np
a = np.array([0.0, 0.01, 1.0, 2.0, 2.001, 2.002])
mask = np.isclose(a, a.astype(int))

print(a[~mask])
#[ 0.01   2.001  2.002]
SpghttCd
  • 10,510
  • 2
  • 20
  • 25
  • 3
    As a general rule always use `isclose` when comparing floats. I'm not sure it's necessary here, but upvoted for good practice. – Daniel F Aug 30 '18 at 10:37
  • 1
    It's not a good practice to blindly follow what is called "good practice". `isclose`, depending on the source of these numbers, may actually be actively harmful. – Ruslan Aug 31 '18 at 06:03
18

Mask with whether each element is equal to it as an integer.

arr = np.array([0.0, 0.01, 1.0, 2.0, 2.001, 2.002])
out = arr[arr != arr.astype(int)]
#np.array([0.01, 2.001, 2.002])
Joe Iddon
  • 20,101
  • 7
  • 33
  • 54
6

I know of no in-built function. But you can create one yourself:

import numpy as np

A = np.array([0.0, 0.01, 1.0, 2.0, 2.001, 2.002])

def remove_ints(arr):
    return arr[~(arr == arr.astype(int))]

res = remove_ints(A)

array([ 0.01 ,  2.001,  2.002])

Aside, you should not use a built-in class such as input as a variable name.

jpp
  • 159,742
  • 34
  • 281
  • 339
6

I've always used np.equal with np.mod:

>>> A[~np.equal(np.mod(A, 1), 0)]
array([0.01 , 2.001, 2.002])
user3483203
  • 50,081
  • 9
  • 65
  • 94
4

If you do not have to much data (short list), maybe do not need numpy:

>>> i = [0.0, 0.01, 1.0, 2.0, 2.001, 2.002]
>>> a=[j for j in i if not j.is_integer()]
>>> a
['0.01', '2.001', '2.002']

Otherwise see Joe Iddon answer

Dadep
  • 2,796
  • 5
  • 27
  • 40
2

I don't know any builtin for this but you can filter those floats using:

filter(lambda x: int(str(x).split('.')[1]) != 0, input)

The lambda expression here checks if the decimal places are zero which I interpret as the number being an int.

MarianD
  • 13,096
  • 12
  • 42
  • 54
meissner_
  • 556
  • 6
  • 10
  • precision is lost by converting to string. e.g `2.001` becomes `2.0009999999999999`. – Oli Aug 30 '18 at 11:34
  • What? I just tried replicating this but `[str(x) for x in input]` returned: `['0.0', '0.01', '1.0', '2.0', '2.001', '2.002']`? But even if i assume a loss of accuracy, it wouldn't change the results since '001' will not come out as 0 after the int cast, just like '00099999'. – meissner_ Aug 30 '18 at 11:42
  • It happend in my python. Actually these are indexes of pandas dataframe, so loss of precision mean, i can't get back values by apply `.loc` method. – Oli Aug 30 '18 at 11:44
  • Well, this would be very interesting indeed if you can find a way to replicate the effect... – meissner_ Aug 30 '18 at 11:50
0

I had a similar question a while back: Numpy: Check if float array contains whole numbers. The simplest way to mask fractions that I am currently aware of is

mask = ((input % 1) != 0)

You can then apply the mask directly with

output = input[mask]

It bothered me that there is no built-in function to determine the integerness of a float quickly, so I wrote a fast ufunc that provides the functionality of float.is_integer for numpy. You can download from github and compile if you're interested:

from is_integer_ufunc import is_integer

output = input[~is_integer(input)]

I'll see if the numpy community wants to consider adding something like that to the core library. The question seems to come up often enough to justify it.

Mad Physicist
  • 107,652
  • 25
  • 181
  • 264