Python Numpy-如何将向量索引数组转换为掩码?
给定一个名为Python Numpy-如何将向量索引数组转换为掩码?,python,numpy,Python,Numpy,给定一个名为index的np.ndarray,每行有n行和可变长度向量,我想创建一个n行和m行的布尔掩码,其中m是一个已知值,等于索引中可能的最大值。 请注意,索引中指定的索引是指每行索引,而不是全局矩阵索引 例如,假设: index=np.array([ [2, 0], [0], [4, 7, 1] ]) #预期产量 打印(遮罩) [[True-False-False-False] [真假假假假] [假真假假假假真]] m是预先知道的(在mask中每行的最大长度),不需要从索引中推断出来 注
index
的np.ndarray
,每行有n
行和可变长度向量,我想创建一个n
行和m
行的布尔掩码,其中m
是一个已知值,等于索引中可能的最大值。
请注意,索引
中指定的索引是指每行索引,而不是全局矩阵索引
例如,假设:
index=np.array([
[2, 0],
[0],
[4, 7, 1]
])
#预期产量
打印(遮罩)
[[True-False-False-False]
[真假假假假]
[假真假假假假真]]
m
是预先知道的(在mask
中每行的最大长度),不需要从索引中推断出来
注意:这不同于将索引数组转换为掩码,其中索引引用生成的矩阵索引-
def mask_from_indices(indices, ncols=None):
# Extract column indices
col_idx = np.concatenate(indices)
# If number of cols is not given, infer it based on max column index
if ncols is None:
ncols = col_idx.max()+1
# Length of indices, to be used as no. of rows in o/p
n = len(indices)
# Initialize o/p array
out = np.zeros((n,ncols), dtype=bool)
# Lengths of each index element that represents each group of col indices
lens = np.array(list(map(len,indices)))
# Use np.repeat to generate all row indices
row_idx = np.repeat(np.arange(len(lens)),lens)
# Finally use row, col indices to set True values
out[row_idx,col_idx] = 1
return out
样本运行-
In [89]: mask_from_indices(indices)
Out[89]:
array([[ True, False, True, False, False, False, False, False],
[ True, False, False, False, False, False, False, False],
[False, True, False, False, True, False, False, True]])
以下是一个变体:
def create_mask(indices, m):
mask = np.zeros((len(indices), m), dtype=bool)
for i, idx in enumerate(indices):
mask[i, idx] = True
return mask
用法:
>>> create_mask(indices, 8)
array([[ True, False, True, False, False, False, False, False],
[ True, False, False, False, False, False, False, False],
[False, True, False, False, True, False, False, True]])
虽然没有以完全矢量化的方式直接实现这一点,但对于较大的输入,一次应用带有预先计算的完整索引列表的屏蔽[完整行索引,完整列索引]
比多次应用屏蔽[部分行索引,部分列索引]
更快。
内存方面,多个应用程序的要求也较低,因为不需要构建中间全行索引
/全列索引
。
当然,这通常取决于索引的长度
为了了解不同解决方案的速度,我们对以下功能进行了测试:
将numpy导入为np
随机输入
def gen_mask_direct(列索引,列=无):
如果cols为无:
cols=np.max(np.concatenate(col_索引))+1
行=列(列索引)
掩码=np.0((行,列),数据类型=bool)
对于行索引,枚举中的列索引(列索引):
掩码[行索引,列索引]=真
返回掩码
def gen_掩码_循环(列索引,列=无):
行=列(列索引)
行索引=元组(i表示i,j表示枚举中的j(列索引)表示j中的u)
列索引=元组(和(列索引,())
如果cols为无:
cols=np.max(col_指数)+1
掩码=np.0((行,列),数据类型=bool)
掩码[行索引,列索引]=真
返回掩码
def gen_掩码_np_重复(列索引,列=无):
行=列(列索引)
长度=列表(映射(长度、列索引))
行索引=np.重复(np.排列(行),长度)
列索引=np.连接(列索引)
如果cols为无:
cols=np.max(col_指数)+1
掩码=np.0((行,列),数据类型=bool)
掩码[行索引,列索引]=真
返回掩码
def gen_mask_np_串联(列索引,列=无):
行=列(列索引)
行索引=元组(np.full(len(col_索引),i)表示i,枚举中的col_索引(col_索引))
行索引=np.连接(行索引)
列索引=np.连接(列索引)
如果cols为无:
cols=np.max(col_指数)+1
掩码=np.0((行,列),数据类型=bool)
掩码[行索引,列索引]=真
返回掩码
gen\u mask\u direct()
基本上实现了mask[部分行索引,部分列索引]
的多种应用。
所有其他应用程序都实现了一次屏蔽[全行索引,全列索引]
,使用不同的方法准备全行索引和全列索引
:
gen\u mask\u loops()
使用直接循环
gen\u mask\u np\u repeat()
使用np.repeat()
(它与
gen\u mask\u np\u concatenate()
使用np.full()
和np.concatenate()的组合
快速健康检查表明所有这些都是等效的:
funcs=gen\u mask\u direct、gen\u mask\u循环、gen\u mask\u np\u repeat、gen\u mask\u np\u concatenate
随机种子(0)
测试单元输入=[
(元组)(
元组(已排序(范围内(random.randint(1,n-1))的集合([random.randint(0,n-1))))
对于范围内的(random.randint(1,n-1)))
适用于范围(5,6)内的n
]
打印(测试输入)
# [((0, 2, 3, 4), (2, 3, 4), (1, 4), (0, 1, 4))]
对于func中的func:
打印('Func:',Func.\uuu name\uuuu)
对于测试输入中的测试输入:
打印(func(测试输入).astype(int))
以下是一些基准测试(使用中的代码):
并以最快的速度缩放:
支持这样一个总体陈述:通常,对于完整索引,单个应用mask[…]
更快,对于部分索引,多个应用mask[…]
更快
为完整起见,以下代码用于生成输入、比较输出、运行基准测试和准备绘图:
def发电机输入(n):
随机种子(0)
返回元组(
元组(已排序(集合([random.randint(0,n-1))用于范围内的uu(random.randint(n//2,n-1))))
对于范围内的u(random.randint(n//2,n-1)))
def均分输出(a、b):
返回np.all(a==b)
输入大小=范围(13)内i的元组(int(2**(2+(3*i)/4))
打印('输入大小:\n',输入大小'\n')
运行时、输入大小、标签、结果=基准(
funcs,gen_input=gen_input,equal_output=equal_output,
输入大小=输入大小)
绘图基准(运行时、输入大小、标签、单位='ms')
绘图基准(运行时、输入大小、标签、单位='ms',缩放速度=2)
你能把你的最后一句话说清楚一点吗?对我来说,这看起来像是你期望的结果。如果你有两个向量,你可以创建一个最大大小的零向量,然后使用索引来做一些事情
Func: gen_mask_direct
[[1 0 1 1 1]
[0 0 1 1 1]
[0 1 0 0 1]
[1 1 0 0 1]]
Func: gen_mask_loops
[[1 0 1 1 1]
[0 0 1 1 1]
[0 1 0 0 1]
[1 1 0 0 1]]
Func: gen_mask_np_repeat
[[1 0 1 1 1]
[0 0 1 1 1]
[0 1 0 0 1]
[1 1 0 0 1]]
Func: gen_mask_np_concatenate
[[1 0 1 1 1]
[0 0 1 1 1]
[0 1 0 0 1]
[1 1 0 0 1]]