【问题标题】:Looping through an array based on the first index根据第一个索引循环遍历数组
【发布时间】:2019-10-14 14:47:33
【问题描述】:

我有两个数组,我想遍历第二个数组,只返回第一个元素等于另一个数组中的元素的数组。

 a = [10, 11, 12, 13, 14]
 b = [[9, 23, 45, 67, 56, 23, 54], [10, 8, 52, 30, 15, 47, 109], [11, 81, 
 152, 54, 112, 78, 167], [13, 82, 84, 63, 24, 26, 78], [18, 182, 25, 63, 96, 
 104, 74]]

我有两个不同的数组,a 和 b。我想找到一种方法来查看 b 中的每个子数组(?),其中 第一个值等于数组 a 中的值以创建一个新数组 c。

我要找的结果是:

  c = [[10, 8, 52, 30, 15, 47, 109],[11, 81, 152, 54, 112, 78, 167],[13, 82, 84, 63, 24, 26, 78]]

Python 有没有一种工具可以以 Excel 的 MATCH() 的方式执行此操作?

我尝试以如下方式循环:

 for i in a:
      if i in b:
          print (b)

但是因为数组中还有其他元素,所以这种方式是行不通的。任何帮助将不胜感激。

问题进一步说明:

a = [5, 6, 7, 9, 12]

我使用 XLRD (b_csv_data) 读取了一个 excel 文件:

 Start  Count   Error   Constant    Result1 Result2 Result3 Result4
 5       41       0       45             23      54      66       19
 5.4     44       1       21             52      35       6       50
 6       16       1       42             95      39       1       13
 6.9     50       1       22             71      86      59       97
 7       38       1       43             50      47      83       67
  8      26       1       29             100     63      15       40
 9       46       0       28             85       9      27       81
 12      43       0       21             74      78      20       85

接下来,我创建了一个可以读取选定行数的外观。为简单起见,上面的这个文件只有几行。我当前的文件大约有 100 行。

for r in range (1, 7): #skipping headers and only wanting first few rows to start

     b_raw = b_csv_data.row_values(r) 
     b = np.array(b_raw) # I created this b numpy array from the line of code above

【问题讨论】:

    标签: python arrays loops numpy indexing


    【解决方案1】:

    使用np.isin -

    In [8]: b[np.isin(b[:,0],a)]
    Out[8]: 
    array([[ 10,   8,  52,  30,  15],
           [ 11,  81, 152,  54, 112],
           [ 13,  82,  84,  63,  24]])
    

    使用排序的a,我们也可以使用np.searchsorted -

    idx = np.searchsorted(a,b[:,0])
    idx[idx==len(a)] = 0
    out = b[a[idx] == b[:,0]]
    

    如果你有一个每行元素数量不同的数组,本质上是列表数组,你需要修改切片部分。所以,在这种情况下,先获取元素 -

    b0 = [bi[0] for bi in b]
    

    然后,使用b0 替换之前发布的方法中b[:,0] 的所有实例。

    【讨论】:

    • 如果我的编辑中反映的数组长度不同怎么办?
    • @user11487335 确保输入 ab 是数组。所以,就像预处理一样 - a=np.array(a); b= np.array(b)。我假设数组就像问题所说的那样。
    • 正确。它们是 numpy 数组。刚刚应用这些更改以确保它们是 numpy 数组并且出现相同的错误:(。行的意义是什么:idx[idx==len(a)] = 0。这是专门挑选第一个索引吗?
    • @user11487335 ab 的形状是什么?您可以使用a.shapeb.shape 获取这些信息。关于第二个 searchsorted 一个,idx 正在根据排序匹配选择索引,并且idx[idx==len(a)] = 0 摆脱了越界的索引。
    • 我的代码中的 a 是 (75, ) 而 b 是 (22, ), (22, ), (22, ), (22, )
    【解决方案2】:

    你正在做相反的事情。最好循环遍历 b 数组的元素并检查它是否存在于 a 中。如果是,则打印 b 的那个元素。请参阅下面的答案。

    a = [10, 11, 12, 13, 14]
    b = [[9, 23, 45, 67, 56, 23, 54], [10, 8, 52, 30, 15, 47, 109], [11, 81, 152, 54, 112, 78, 167], [13, 82, 84, 63, 24, 26, 78], [18, 182, 25, 63, 96, 104, 74]]
    
    for bb in b:  # if you want to check only the first element of b is in a
        if bb[0] in a:
                print(bb)
    
    for bb in b:   # if you want to check if any element of b is in a
        for bbb in bb:
            if bbb in a:
                print(bb)
    

    输出:

    [10, 8, 52, 30, 15, 47, 109]
    [11, 81, 152, 54, 112, 78, 167]
    [13, 82, 84, 63, 24, 26, 78]
    

    【讨论】:

    • 我尝试在模式代码中应用此技术,但输出为 IndexError: invalid index to scalar variable。我的 b 数组正在通过 XLRD 读取 excel 文件来复制。然后我创建了一个循环来仅读取前几行,因为我目前正在处理数百行。对于我读过的那几行,我只想选择第一个值在 a 数组中的行。
    【解决方案3】:

    使用列表理解:

    c = [l for l in b if l[0] in a]
    

    输出:

    [[10, 8, 52, 30, 15], [11, 81, 152, 54, 112], [13, 82, 84, 63, 24]]
    

    如果您的listarrays 相当大,使用numpy.isin 会明显更快:

    b[np.isin(b[:, 0], a), :]
    

    基准测试:

    a = [10, 11, 12, 13, 14]
    b = [[9, 23, 45, 67, 56], [10, 8, 52, 30, 15], [11, 81, 152, 54, 112], 
     [13, 82, 84, 63, 24], [18, 182, 25, 63, 96]]
    
    list_comp, np_isin = [], []
    for i in range(1,100):
        a_test = a * i
        b_test = b * i
        list_comp.append(timeit.timeit('[l for l in b_test if l[0] in a_test]', number=10, globals=globals()))
        a_arr = np.array(a_test)
        b_arr = np.array(b_test)
        np_isin.append(timeit.timeit('b_arr[np.isin(b_arr[:, 0], a_arr), :]', number=10, globals=globals()))
    

    虽然不够清晰和简洁,但如果 b 小于 100,我建议使用 list 理解。否则,numpy 是您的选择。

    【讨论】:

    • 即使是 numpy 数组?
    • @user11487335 取决于列表或数组的长度。如果它们的长度与示例相似,我建议使用list 而不是numpy
    • 谢谢。我进行了编辑,其中它们的长度不相似。我喜欢 numpy 的 isin 功能,但这只适用于相似的长度?
    • @user11487335 子数组的长度并不重要。 b 的长度是最重要的。看看我刚刚发布的基准 :)
    • 不确定是否被否决,但仅凭基准就值得这篇文章。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-06-30
    • 1970-01-01
    • 2017-10-24
    • 1970-01-01
    • 2013-11-06
    • 2011-10-07
    • 1970-01-01
    相关资源
    最近更新 更多