python - 不可靠的 mylist.count(nan) 并且没有警告
问题描述
我有一个值列表。某些值已损坏并表示为“nan”。在处理了一些数据之后,“nan”按预期和预期传播。
在操纵的数据集中,我想找到无用值的数量。直觉上,我使用了 method .count(nan)
,但令我惊讶的是,在没有警告的情况下,只计算了“未经处理的”nans。
我在 docs.python math.nan中没有立即找到答案,并且list.count(x) 方法 的文档不是很精确:
返回 x 在列表中出现的次数。
from math import nan, isnan
list1 = [nan]
myitem1 = list1[0]
myitem2 = list1[0] + 1 # common operation: extract a value from a list
print(myitem2) # nan: looks like nan
print(isnan(myitem2)) # True: is nan
list2 = [1, nan, myitem1, myitem2]
count1 = list2.count(nan)
count2 = sum(isnan(e) for e in list2)
print(count1, count2) # 2, 3: doesn't always count as nan
解决方案
虽然myitem2
有一个 NaN 值,但它是一个不同于 的float
实例math.nan
,因为+
运算符总是返回一个新对象,即使它具有相同的值。
list2.count(nan)
只返回列表中包含的次数math.nan
。
它有助于查看对象 ID(示例值,每次运行代码时它们都不同):
>>> id(nan)
140305278866152
>>> id(myitem2)
140305278866176
>>> [id(x) for x in list2]
[9079008, 140305278866152, 140305278866152, 140305278866176]
# 1 nan nan myitem2
现在你可能会问,
>>> a = 5.0
>>> b = a + 0
>>> list3 = [a, b]
>>> id(a)
140133123191696
>>> id(b)
140133123191504
>>> [id(x) for x in list3]
[140133123191696, 140133123191504]
>>> list3.count(a)
2
为什么这不返回 1,因为a
两个b
不同的对象具有相同的值?
解释是,count
实际上首先将每个列表项与它的参数按身份进行比较,但如果不同,则按值进行比较。
我没有找到指定的位置,但这里是 CPython实现(我添加的评论):
static PyObject *
list_count(PyListObject *self, PyObject *value)
{
Py_ssize_t count = 0;
Py_ssize_t i;
for (i = 0; i < Py_SIZE(self); i++) {
PyObject *obj = self->ob_item[i];
// comparison by identity
if (obj == value) {
count++;
continue;
}
Py_INCREF(obj);
// comparison by value
int cmp = PyObject_RichCompareBool(obj, value, Py_EQ);
Py_DECREF(obj);
if (cmp > 0)
count++;
else if (cmp < 0)
return NULL;
}
return PyLong_FromSsize_t(count);
}
最后,您需要知道按值将任何内容与 NaN 进行比较总是返回“不等于”,即使另一个值也是 NaN(我也没有找到为 Python 指定的位置,但请参阅Why does compare to nan yield False (Python)?以及对于 IEEE754 NaN 值返回 false 的所有比较的基本原理是什么?)。
这就是为什么myitem2
不包含在 中.count(nan)
,而是b
包含在 中的原因.count(a)
。
推荐阅读
- r - 具有超过 2 个 data.frames 后缀的嵌套 full_join
- routes - 卡车路线违规问题
- sql - 在 SQL 查询中使用 XMLNamespaces
- html - 我将如何将我的 3 个按钮集中在我的网页上?
- express - Heroku:构建后没有这样的文件或目录
- semantic-ui - 如何通过单击来更新反应语义 UI 进度条的值?
- javascript - 打字稿:数组的函数查找正在工作,但如果我检查它是否使用 if 语句返回一个值,它就不起作用
- sql - 直接实现EF Core多对多关系无法检测到相关表
- python-3.x - 从流式视频中抓取图像链接
- java - 如何使用 ANTLR 访问者处理逻辑连接的表达式