从numpy数组中高效删除None的方法

32

有没有一种有效的方法可以从numpy数组中删除None值,并将数组调整为其新的大小?

例如,如何在不使用python迭代的情况下从此框架中删除None值。我可以轻松地遍历它,但正在开发一个可能被多次调用的API调用。

a = np.array([1,45,23,23,1234,3432,-1232,-34,233,None])

2
你想用什么替换None吗?还是你想先删除None,然后调整数组大小? - Nick ODell
我想要移除None值并调整数组大小。 - Michael WS
!= 比 filter 更高效。 - Michael WS
另外,你不能像之前的例子那样使用“!= None”。 - Michael WS
2个回答

53
In [17]: a[a != np.array(None)]
Out[17]: array([1, 45, 23, 23, 1234, 3432, -1232, -34, 233], dtype=object)
上述方法之所以有效,是因为 a != np.array(None) 是一个布尔数组,用于映射非 None 值:
In [20]: a != np.array(None)
Out[20]: array([ True,  True,  True,  True,  True,  True,  True,  True,  True, False], dtype=bool)

以这种方式选择数组元素被称为布尔数组索引


请问一下,如果数组中有n个项目,这种方法比O(n)更快吗? - wookie919
3
这让我在处理大数组时节省了80%的时间。 - Michael WS
如果我正确理解了numpy的内部机制,那么这是在复制数组并逐个删除None。所以,我认为不是这样。 - Nick ODell
2
但是大部分代码将使用C语言编写。它比filter快得多。 - Michael WS
在访问(索引)操作符中使用比较是否有名称?就像访问器中的冒号被称为切片一样。 - Kevin
@Kevin 这被称为布尔数组索引 - John1024

5

我使用以下方法,我觉得比被接受的答案更简单:

a = a[a != None]

注意:PEP8警告不要使用等号运算符与单例(例如None)一起使用。当我发布这个答案时,我不知道这一点。话虽如此,对于NumPy数组,我发现这太具有Python特色和美观以至于不能不使用。请参见评论中的讨论。

虽然这种写法更简单,但它无法与PEP8自动格式化工具(如flake8)配合使用,因为它会将a[a != None]转换为a[a is not None](这在语义上并不等价)。 - David Slater
PEP8 中没有关于不使用 != 的规定,至少我没有看到。需要考虑的是:有时候使用 is 是合适的,而有时候则需要使用 ==。同样地,有时候你需要使用 !=,而有时候则需要使用 is not。你只需要知道自己在做什么。请注意,这个问题/答案与 numpy 数组有关 -- 对于 Python 列表,你需要另外考虑。 - eric
1
从[PEP8](https://www.python.org/dev/peps/pep-0008/#programming-recommendations)中可以了解到:“始终应使用is或is not,而不是等于运算符来比较单例对象,例如None。” 我理解这是关于numpy的,而不是Python列表。 - David Slater
哎呀,我没注意到那个。答案中的结构很好,但是需要注意!:) 我很高兴在这种情况下违反建议,但很高兴你指出了它。讨论在这里:https://dev59.com/Jmgu5IYBdhLWcg3wrIuR - eric
2
你的回答是我以前一直使用的方法... 直到我们在代码库中开始使用flake8(和autopep8) - 这导致代码更改(有时自动更改)为a = a [a is not None],这导致了一些奇怪的错误。感谢提供链接 - 很好的讨论! - David Slater
1
@DavidSlater 我学到了有关PEP8的新知识,并在我的回答中添加了一个警告。谢谢! - eric

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接