【问题标题】:iterating a filtered Numpy array whilst maintaining index information在维护索引信息的同时迭代过滤的 Numpy 数组
【发布时间】:2020-05-23 05:56:22
【问题描述】:

我正在尝试将过滤后的值从 Numpy 数组传递到函数中。 我只需要传递某个值以上的值,并将它们的索引位置与 Numpy 数组一起传递。

我试图通过使用 Numpys 自己的过滤系统来避免在 python 中迭代整个数组,我正在处理的数组中有 20k 个值,其中可能只有很少的相关值。

import numpy as np

somearray = np.array([1,2,3,4,5,6])
arrayindex = np.nonzero(somearray > 4)

for i in arrayindex:
    somefunction(arrayindex[0], somearray[arrayindex[0]])

这引发了无法处理多个值的逻辑错误, 这导致我通过 print 语句对其进行测试以查看发生了什么。

for cell in arrayindex:
    print(f"index {cell}")
    print(f"data {somearray[cell]}")

我期望的输出是

index 4
data 5
index 5
data 6

但是我得到了

index [4 5]
data [5 6]

我已经查看了不同的方法来遍历 numpy 数组和 neditor,但似乎没有一个仍然允许我在 for 循环之外对值进行过滤。

我的困惑有解决方案吗?

哦,我知道循环遍历 numpy 数组通常不受欢迎,但是我将这些值传递给的函数很复杂,会触发某些事件并涉及要上传到依赖于数据库的数据数组中的数据位置。

谢谢。

【问题讨论】:

标签: python arrays function numpy loops


【解决方案1】:

您需要清楚地了解nonzero 产生的内容,并注意使用列表和元组进行索引之间的区别。

===

In [110]: somearray = np.array([1,2,3,4,5,6]) 
     ...: arrayindex = np.nonzero(somearray > 4)                                               

nonzero 生成一个数组元组,每个维度一个(这在二维数组中变得更加明显):

In [111]: arrayindex                                                                           
Out[111]: (array([4, 5]),)

可以直接作为索引使用:

In [113]: somearray[arrayindex]                                                                
Out[113]: array([5, 6])

在这种一维情况下,您可以将数组从元组中取出,然后对其进行迭代:

In [114]: for i in arrayindex[0]:print(i, somearray[i])                                        
4 5
5 6

argwhere 做了一个“转置”,也可以用于迭代

In [115]: idxs = np.argwhere(somearray>4)                                                      
In [116]: idxs                                                                                 
Out[116]: 
array([[4],
       [5]])
In [117]: for i in idxs: print(i,somearray[i])                                                 
[4] [5]
[5] [6]

idxs 是 (2,1) 形状,所以 i 是 (1,) 形状数组,导致显示中的括号。有时它很有用,但nonzero 被更多地使用(通常是它的另一个名称,np.where)。

2d

argwhere 有一个 2d 示例:

In [119]: x=np.arange(6).reshape(2,3)                                                          
In [120]: np.argwhere(x>1)                                                                     
Out[120]: 
array([[0, 2],
       [1, 0],
       [1, 1],
       [1, 2]])
In [121]: np.nonzero(x>1)                                                                      
Out[121]: (array([0, 1, 1, 1]), array([2, 0, 1, 2]))
In [122]: x[np.nonzero(x>1)]                                                                   
Out[122]: array([2, 3, 4, 5])

虽然nonzero 可用于索引数组,但argwhere 元素不能。

In [123]: for ij in np.argwhere(x>1): 
     ...:     print(ij,x[ij]) 
     ...:                                                                                      
...
IndexError: index 2 is out of bounds for axis 0 with size 2

问题是ij 是一个列表,用于对维度进行索引。 numpy 在索引时区分列表和元组。 (早期版本捏造了差异,但当前版本采取了更严格的方法。)

所以我们需要把列表变成一个元组。一种方法是解压:

In [124]: for i,j in np.argwhere(x>1): 
     ...:     print(i,j,x[i,j]) 
     ...:      
     ...:                                                                                      
0 2 2
1 0 3
1 1 4
1 2 5

我本可以在 [123] 中使用:print(ij,x[tuple(ij)])

我应该使用解包 [117] 迭代:

In [125]: for i, in idxs: print(i,somearray[i])                                                
4 5
5 6

somearray[tuple(i)]

【讨论】:

    【解决方案2】:
    import numpy as np
    somearray = np.array([1,2,3,4,5,6])
    arrayindex = [idx for idx, val in enumerate(somearray) if val > 4]
    
    for i in range(0, len(arrayindex)):
        somefunction(arrayindex[i], somearray[arrayindex[i]])
    
    for i in range(0, len(arrayindex)):
        print("index", arrayindex[i])
        print("data", somearray[arrayindex[i]])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-17
      • 1970-01-01
      • 2016-01-28
      • 1970-01-01
      • 1970-01-01
      • 2021-11-28
      • 1970-01-01
      • 2011-12-28
      相关资源
      最近更新 更多