我很难调试一个问题,其中 list
中的 float nan
和 中的
在 nan
numpy.arrayitertools.groupby
中使用时的处理方式不同:
给定以下列表和数组:
from itertools import groupby
import numpy as np
lst = [np.nan, np.nan, np.nan, 0.16, 1, 0.16, 0.9999, 0.0001, 0.16, 0.101, np.nan, 0.16]
arr = np.array(lst)
当我遍历列表时,连续的 nan
被分组:
>>> for key, group in groupby(lst):
... if np.isnan(key):
... print(key, list(group), type(key))
nan [nan, nan, nan] <class 'float'>
nan [nan] <class 'float'>
但是,如果我使用数组,它会将连续的 nan
放在不同的组中:
>>> for key, group in groupby(arr):
... if np.isnan(key):
... print(key, list(group), type(key))
nan [nan] <class 'numpy.float64'>
nan [nan] <class 'numpy.float64'>
nan [nan] <class 'numpy.float64'>
nan [nan] <class 'numpy.float64'>
即使我将数组转换回列表:
>>> for key, group in groupby(arr.tolist()):
... if np.isnan(key):
... print(key, list(group), type(key))
nan [nan] <class 'float'>
nan [nan] <class 'float'>
nan [nan] <class 'float'>
nan [nan] <class 'float'>
我正在使用:
numpy 1.11.3
python 3.5
我知道通常 nan != nan
为什么这些操作会给出不同的结果? groupby
怎么可能对 nan
进行分组?
最佳答案
Python 列表只是指向内存中对象的指针数组。特别是 lst
包含指向对象 np.nan
的指针:
>>> [id(x) for x in lst]
[139832272211880, # nan
139832272211880, # nan
139832272211880, # nan
139832133974296,
139832270325408,
139832133974296,
139832133974464,
139832133974320,
139832133974296,
139832133974440,
139832272211880, # nan
139832133974296]
(np.nan
在我的电脑上是 139832272211880。)
另一方面,NumPy 数组只是连续的内存区域;它们是由 NumPy 解释为值序列( float 、整数等)的位和字节区域。
问题在于,当您要求 Python 迭代包含浮点值的 NumPy 数组时(在 for
循环或 groupby
级别),Python 需要将这些值装箱字节转换为适当的 Python 对象。它在迭代时为数组中的每个单个值在内存中创建一个全新的 Python 对象。
例如,您可以看到在调用 .tolist()
时为每个 nan
值创建了不同的对象:
>>> [id(x) for x in arr.tolist()]
[4355054616, # nan
4355054640, # nan
4355054664, # nan
4355054688,
4355054712,
4355054736,
4355054760,
4355054784,
4355054808,
4355054832,
4355054856, # nan
4355054880]
itertools.groupby
能够对 Python 列表的 np.nan
进行分组,因为它在比较 Python 对象时首先检查 identity .因为这些指向 nan
的指针都指向同一个 np.nan
对象,所以分组是可能的。
但是,对 NumPy 数组的迭代不允许此初始身份检查成功,因此 Python 回退到检查相等性和 nan != nan
正如您所说。
关于python - 为什么 itertools.groupby 可以将 NaN 分组在列表中而不是在 numpy 数组中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41723419/