在NumPy数组中删除行

108

我有一个可能长这样的数组:

ANOVAInputMatrixValuesArray = [[ 0.96488889, 0.73641667, 0.67521429, 0.592875, 
0.53172222], [ 0.78008333, 0.5938125, 0.481, 0.39883333, 0.]]

注意到其中一行末尾有一个零值。 我想删除任何包含零的行,同时保留所有单元格中都不为零的行。

但是每次填充数组时,它的行数将不同,并且零将位于不同的行中。

我使用以下代码获取每行中非零元素的数量:

NumNonzeroElementsInRows    = (ANOVAInputMatrixValuesArray != 0).sum(1)
对于上述数组,NumNonzeroElementsInRows 包含:[5 4]。
其中五表示第0行中所有可能的值都是非零的,而四表示第1行中可能的一个值是零。
因此,我正在尝试使用以下代码来查找并删除包含零值的行。
for q in range(len(NumNonzeroElementsInRows)):
    if NumNonzeroElementsInRows[q] < NumNonzeroElementsInRows.max():
        p.delete(ANOVAInputMatrixValuesArray, q, axis=0)

但出于某种原因,尽管许多打印命令表明所有变量在代码之前都被正确地填充,但此代码似乎没有任何作用。

肯定有一种简单的方法可以“删除包含零值的任何行”。

有人能展示给我编写什么代码来实现这个功能吗?

6个回答

208
最简单的从数组中删除行和列的方法是使用`numpy.delete`函数。
假设我有以下数组`x`:
x = array([[1,2,3],
        [4,5,6],
        [7,8,9]])

要删除第一行,请执行以下操作:

x = numpy.delete(x, (0), axis=0)

要删除第三列,请执行以下操作:

x = numpy.delete(x,(2), axis=1)

你可以找到那些包含0的行的索引,将它们放在列表或元组中,并将其作为该函数的第二个参数传递。


2
谢谢!我也遇到了同样的问题,而且我无法弄清楚为什么简单地调用 numpy.delete(x, index) 就不起作用。 - Antimony
7
请注意,numpy delete()文档指出,“通常最好使用布尔掩码”,因为会返回一个新数组 - 在该链接下提供了一个示例。 - arturomp
3
但是遮罩是非破坏性的。调用delete()会消耗时间和内存吗? - Nathan majicvr.com

14

这里是一行代码(是的,它与user333700的类似,但更直观易懂):

>>> import numpy as np
>>> arr = np.array([[ 0.96488889, 0.73641667, 0.67521429, 0.592875, 0.53172222], 
                [ 0.78008333, 0.5938125, 0.481, 0.39883333, 0.]])
>>> print arr[arr.all(1)]
array([[ 0.96488889,  0.73641667,  0.67521429,  0.592875  ,  0.53172222]])

顺便提一下,对于大矩阵而言,这种方法比屏蔽数组的方法要快得多。对于一个2048 x 5的矩阵,这种方法大约快了1000倍。

顺便说一下,根据用户333700的评论中的方法,在我的测试中速度略快,虽然我不知道为什么。


3
"any"可以短路,一旦检测到第一个真实情况,它就可以停止,而"all"必须检查所有条件。因此,在一般情况下,not(在numpy中为“〜”)any应该比all更快。 - Josef
5
@user333700,它们两个都可以进行短路运算,只是针对不同的情况。any会在第一个为真的情况下短路并返回true;all会在第一个为假的情况下短路并返回false。在这种情况下,短路应该是平局,但我认为加上额外的not会使其变慢。 - Justin Peel

5

这与您原始的方法类似,将使用比unutbu的答案更少的空间,但我怀疑它会更慢。

>>> import numpy as np
>>> p = np.array([[1.5, 0], [1.4,1.5], [1.6, 0], [1.7, 1.8]])
>>> p
array([[ 1.5,  0. ],
       [ 1.4,  1.5],
       [ 1.6,  0. ],
       [ 1.7,  1.8]])
>>> nz = (p == 0).sum(1)
>>> q = p[nz == 0, :]
>>> q
array([[ 1.4,  1.5],
       [ 1.7,  1.8]])

顺便说一下,你的代码行

p.delete() 对我无效 - ndarray 没有 .delete 属性。


8
更简洁的写法:p[(p!=0).any(axis=1)] 对于行更明确的写法:p[(p!=0).any(axis=1), :] - Josef

2

NumPy提供了一个简单的函数来完成同样的操作:假设您有一个掩码数组'a',调用numpy.ma.compress_rows(a)将删除包含掩码值的行。我猜这种方式要快得多...


1
import numpy as np 
arr = np.array([[ 0.96488889, 0.73641667, 0.67521429, 0.592875, 0.53172222],[ 0.78008333, 0.5938125, 0.481, 0.39883333, 0.]])
print(arr[np.where(arr != 0.)])

-1

我可能回答这个问题有点晚了,但是想分享我的意见,以造福社区。对于这个例子,让我称您的矩阵为“ANOVA”,并且我假设您只是想从该矩阵中删除第5列中仅包含0的行。

indx = []
for i in range(len(ANOVA)):
    if int(ANOVA[i,4]) == int(0):
        indx.append(i)

ANOVA = [x for x in ANOVA if not x in indx]

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