Numpy:检查float数组是否包含整数

时间:2016-01-27 15:58:50

标签: python numpy floating-point

在Python中,可以使用float检查n.is_integer()是否包含整数值,基于此QA:How to check if a float value is a whole number

numpy是否有类似的操作可以应用于数组?允许以下内容的东西:

>>> x = np.array([1.0 2.1 3.0 3.9])
>>> mask = np.is_integer(x)
>>> mask
array([True, False, True, False], dtype=bool)

可以执行类似

的操作
>>> mask = (x == np.floor(x))

>>> mask = (x == np.round(x))

但它们涉及调用额外的方法并创建一堆可能被避免的临时数组。

numpy是否有一个矢量化函数,以类似于Python float.is_integer的方式检查浮点数的小数部分?

4 个答案:

答案 0 :(得分:4)

据我所知,没有这样的函数返回一个布尔数组,指示浮点数是否具有小数部分。我能找到的最接近的是np.modf,它返回小数和整数部分,但是会创建两个浮点数组(至少是暂时的),所以它可能不是最好的内存方式。

如果您在工作中感到高兴,可以尝试以下方式:

>>> np.mod(x, 1, out=x)
>>> mask = (x == 0)

这可以节省内存而不是使用圆形或地板(你必须保持x),但当然你会失去原来的x

另一个选择是要求它在Numpy中实现,或者自己实现它。

答案 1 :(得分:3)

我需要回答这个问题的原因略有不同:检查何时我可以将整个浮点数数组转换为整数而不会丢失数据。

Hunse的回答几乎对我有用,除了我显然无法使用就地技巧,因为我需要能够撤消操作:

if np.all(np.mod(x, 1) == 0):
    x = x.astype(int)

从那里开始,我想到了以下选项,在许多情况下可能更快:

x_int = x.astype(int)
if np.all((x - x_int) == 0):
    x = x_int

原因是模运算比减法慢。但是,现在我们预先对整数进行投射 - 相对而言,我不知道该操作的速度有多快。但是,如果你的数组的大多数是整数(它们在我的情况下),后一版本几乎肯定更快。

另一个好处是,您可以用np.isclose之类的内容替换子代码以检查某个容差(当然,您应该小心,因为截断不是正确的舍入!)。

x_int = x.astype(int)
if np.all(np.isclose(x, x_int, 0.0001)):
    x = x_int

编辑:较慢,但也许值得,取决于您的用例,如果存在,也会单独转换整数。

x_int = x.astype(int)
safe_conversion = (x - x_int) == 0
# if we can convert the whole array to integers, do that
if np.all(safe_conversion):
    x = x_int.tolist()
else:
    x  = x.tolist()
    # if there are _some_ integers, convert them
    if np.any(safe_conversion):
        for i in range(len(x)):
            if safe_conversion[i]:
                x[i] = int(x[i])

作为一个重要的例子:这对我有用,因为我有稀疏数据(这意味着大多数为零)然后我转换为JSON一次,然后在服务器上重用。对于浮点数,ujson将这些转换为[ ...,0.0,0.0,0.0,... ],对于生成[...,0,0,0,...]的整数,可以保存字符串中字符数的一半。这减少了服务器(较短的字符串)和客户端(较短的字符串,可能稍微更快的JSON解析)的开销。

答案 2 :(得分:1)

您也可以在列表理解中使用Python方法。

>>> x = np.array([1.0, 2.1, 3.0, 3.9])
>>> mask = np.array([val.is_integer() for val in x])
>>> mask
array([ True, False,  True, False])

the answer using mod 1相比,对于具有4个值(5.66 us对8.03 us)的给定示例而言,这稍快一些,而对于1000个值的数组则要快3倍以上。

答案 3 :(得分:0)

受已接受答案的启发,这里有一个使用 % 运算符的非就地版本:

modulus = x % 1
mask = modulus == 0

或者更简洁

mask = (x % 1) == 0
相关问题