在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
的方式检查浮点数的小数部分?
答案 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