映射位置满足数组

时间:2018-05-09 16:05:35

标签: python numpy indexing mapping conditional-statements

给定一个逻辑数组(True / False值)和一系列可能不从0开始的索引,我想创建一个与该范围大小相同的新数组,其中每个元素包含最近的前一个True的索引。

逻辑数组的示例,例如:

[1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0]

和指数的子集:
[0, 1, 2, 3, 4, 5, 6, 7](此处,从0开始,但可能不必)

结果将是:

[0, 0, 0, 3, 4, 5, 5, 7]

我有一个可行的解决方案(下面),但我正在寻找更快的和/或更优雅和/或更可读的替代品,因为阵列的大小可以从数千到数百万不等。

import numpy as np

def map_nearest_preceding_true_indices(tmask, irange):

    true_indices = np.where(tmask)[0]
    mapped_indices = np.empty(len(irange), dtype=np.int)

    for i, index in enumerate(irange):
        index_loc = np.where(true_indices <= index)[0][-1]
        mapped_indices[i] = true_indices[index_loc]

    return mapped_indices

2 个答案:

答案 0 :(得分:1)

有一个单行列表理解:

data = [1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0]
indices = [0, 1, 2, 3, 4, 5, 6, 7]

nearest_true = [next(v for v in range(ind, -1, -1) if data[v]) for ind in indices]

对于indices数组中的每个索引,next从该索引开始向后遍历数据数组,并返回包含truthy值的数据数组的第一个索引。

但是,正如评论中所讨论的,如果任何索引在其后面或后面没有至少一个真值,则此代码将失败。我们可以通过提供next()的默认值来解决这个问题,将其作为第二个参数传递,在这种情况下,我们必须将生成器括起来,因为它不再是唯一的参数:

NOT_FOUND = -1
nearest_true = [next((v for v in range(ind, -1, -1) if data[v]), NOT_FOUND) 
                for ind in indices]

然后,data = [0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0]的输出将为[-1, -1, -1, 3, 4, 5, 5, 7]

答案 1 :(得分:1)

这是一个带有np.searchsorted -

的矢量化解决方案
In [124]: # Considering a more generic case
     ...: tmask = np.array([1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0], dtype=bool)
     ...: irange = np.array([4, 8, 11, 18])

In [125]: map_locations(tmask, irange, invalid_index=-1)
Out[125]: array([4, 7, 9, 9])

In [129]: # Original case with first mask element being false
     ...: tmask = np.array([0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0], dtype=bool).tolist()
     ...: irange = np.array([0, 1, 2, 3, 4, 5, 6, 17]).tolist()

In [130]: map_locations(tmask, irange, invalid_index=-1)
Out[130]: array([-1, -1, -1,  3,  4,  5,  5,  9])

样品运行 -

import tkinter as tk
from tkinter import *
from tkinter import ttk
root = Tk()

class UICreation():
    def __init__(self):
        print ("I m in __init__")
        tabControl = ttk.Notebook(root)
        tab1 = ttk.Frame(tabControl)
        tab2 = ttk.Frame(tabControl)

    def tabCreation(self):
        print ("I M in Tab Creation")
        self.tabControl.add(self.tab1 , text="select ")
        self.tabControl.add(self.tab2, text="Add ")
        self.tabControl.grid()

    def checkBox(self):
        print ("I M in checkBox")
        CheckBox1 = Checkbutton(self.tab1, text="Check1")
        CheckBox1.grid()

if __name__ == '__main__':
    ui = UICreation()
    ui.tabCreation()
    ui.checkBox()
    root.mainloop()