【发布时间】:2017-08-25 01:29:07
【问题描述】:
我们想要选择一维数组v_data 的一些元素。我们需要做的处理需要遍历v_data的子向量。
现在我使用像Gosper's hack 这样的字节逻辑来创建一个整数n_mask,它的二进制表示对应于我想要的v_data 的索引。 n_mask可以通过一个方法转换成二进制向量:
def num2bv(num, n_len):
"""Convert a number to a binary vector of some length"""
return [bool((2**ii & num)//(2**ii)) for ii in reversed(range(0, n_len))]
设置bv_mask = num2bv(n_mask, len(v_data)),运行v_data[bv_using]可以恢复子向量
这是一个不好的方法吗?我特别担心:
- 在实践中使用二进制向量进行索引会很慢
-
num2bv在实践中会很慢 - 能否将此技术用于任何长度的向量取决于 Python 的任意精度整数,这可能很慢或不可移植
这些担忧是否合理?
【问题讨论】:
-
我认为
num2bv确实会很慢。所以你可以考虑用np.unpackbits替换它。但是,这可能不适用于任意精度整数:( -
itertools 有一个功能可以做到这一点,它被称为compress。虽然它不使用位,但它采用任何“真/假”值序列(您应该能够通过生成器生成)。
-
n_len很大(如 1000000),num2bv非常缓慢。这是使用n_len进行的列表理解缩放。相比之下,np.ix_只是np.nonzero,找到所有 True 的索引,并在编译后的代码中进行迭代。v_data[idx]生成的索引列表也比较快。 -
vdata[bv_mask]隐式执行vdata[np.nonzero(bv_mask)](可以在 timeits 中看到。如果vdata是一个列表,itertools.compress很有用,但如果它已经是一个numpy数组,则不需要。数组索引更快。
标签: python performance numpy indexing mask