【问题标题】:Why does a nan of type <class 'numpy.float64'> return -9223372036854775808 as an int64?为什么类型为 <class 'numpy.float64'> 的 nan 将 -9223372036854775808 作为 int64 返回?
【发布时间】:2021-06-06 11:35:11
【问题描述】:

我遇到了一些我觉得奇怪的行为并复制了它。很简单,为什么

np.int64(np.float64(np.nan))

输出

-9223372036854775808

(正如 cmets 中指出的,是的,这是 -2^63,双面 int64 的最大负值)

如果相关或感兴趣,我最初的用例是查看 np.float64 类型的数据帧索引并转换为 np.int64(我通常不会无缘无故地嵌套类型,如上面的简化示例) . 从示例数据框开始:

    0   1
NaN 1   2
1.0 3   4
NaN 5   6

然后运行:

print(df.index.values[0])
print(type(df.index.values[0]))
print(df.index.values[0].astype(np.int64))
print(type(df.index.values[0].astype(np.int64)))

打印:

nan
<class 'numpy.float64'>
-9223372036854775808
<class 'numpy.int64'>

但是,使用 python 类型你不能将 float nan 转换为 int:

print(np.nan)
print(type(np.nan))
print(np.nan.astype(np.int64))

出来:

nan
<class 'float'>
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-130-0d779433eac7> in <module>
      1 print(np.nan)
      2 print(type(np.nan))
----> 3 print(np.nan.astype(np.int64))

AttributeError: 'float' object has no attribute 'astype'

虽然在实践中我能够将 nans 更改为我知道不会是键 (0) 的值 - 我很好奇为什么类 np.float64 类型会这样表现?

【问题讨论】:

  • 整数值没有 NaN 值,因此转换 NaN 可能是未定义的,特别是如果底层库是用 C 实现的。
  • 在Python中进行转换实际上是import math; int(math.nan),这会导致ValueError:Python拦截无效转换。
  • 是 numpy 的 C 利用率导致它的预感还是你确定? (只是好奇,因为这听起来像是一个合理的原因)。在其他地方搜索谷歌时,我无法轻松找到对这个问题的参考。 (我认为即使搜索大的负整数也可以,但没有)。
  • 相关 NumPy 问题:github.com/numpy/numpy/issues/4592。这可能是 NumPy 中的一个错误:numpy.float64(numpy.nan) 抛出一个 ValueError,numpy.int64(numpy.float64(numpy.nan)) 产生 i64 的最小值(对于 i32、u32、u64 类似)。
  • 这本身不是 C 问题(有关此类转换的 C(非)行为,请参阅 stackoverflow.com/questions/10366485/…),但它看起来肯定是 NumPy 问题。

标签: python numpy nan


【解决方案1】:

您的 df.index.values 是一个 numpy 数组:

Out[34]: array([nan,  1., inf])
In [35]: a.dtype
Out[35]: dtype('float64')

数组有一个astype 方法,开发人员选择将像nan 这样的特殊浮点数转换为某种整数(或者如所讨论的允许编译器/处理器这样做)。另一种方法是引发错误。

In [36]: b=a.astype(int)
In [37]: b
Out[37]: array([-9223372036854775808,                    1, -9223372036854775808])
In [38]: b.dtype
Out[38]: dtype('int64')

np.int32np.uint16 等产生不同的值。

使用np.float64 函数创建的对象很像一个0d 数组——它有许多相同的属性和方法,包括astype

In [39]: np.float64(np.nan)
Out[39]: nan
In [40]: np.array(np.nan)
Out[40]: array(nan)
In [41]: Out[39].astype(int)
Out[41]: -9223372036854775808
In [42]: Out[40].astype(int)
Out[42]: array(-9223372036854775808)

另一方面,np.nan 是一个 Python 浮点对象,没有 astype 方法。

python int 也不喜欢这样做:

In [52]: int(np.nan)
Traceback (most recent call last):
  File "<ipython-input-52-03e21f51ddd3>", line 1, in <module>
    int(np.nan)
ValueError: cannot convert float NaN to integer

【讨论】:

    【解决方案2】:

    astype() 是 Pandas 函数。使用 np.nan 时,不能使用 Pandas 函数。而是使用int(np.nan)

    【讨论】:

    • 如果我不接触熊猫的np.int64(np.float64(np.nan)) 是相同的结果:-9223372036854775808
    • 在使用 Pandas 时,您绝对可以使用 np.nan; Pandas 在后台使用了很多 NumPy,并且会尽可能地正确使用它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-06
    • 2017-05-10
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-20
    相关资源
    最近更新 更多