在numpy数组中有效地找到二进制字符串中的位位置

时间:2013-06-10 23:10:10

标签: python string numpy binary pandas

我有一个大的Pandas数据帧(大多数用途的Numpy ndarray的子类),包含二进制字符串(0和1)。我需要找到这些字符串中所有零的位置,然后标记它们。此外,我预计零的位置相对稀疏(约占所有位位置的1%)。

基本上,我想运行这样的东西:

import pandas as pd
x = pd.Series([ '11101110', '11111101' ], ) # start with strings
x = pd.Series([ 0b11101110, 0b11111101 ], ) # ... or integers of a known bit length

zero_positions = find_zero_positions( x )

屈服zero_positions = ......

         value
row bit
0   4        0
    0        0
1   1        0

我已经尝试了几种不同的方法来做到这一点,但没有提出任何比一次循环一行更好的方法。 (编辑:我想看的实际字符串比这里的8位示例长得多,所以查找表不起作用。)

我不确定将此作为字符串问题(Pandas的Vectorized string methods不提供子字符串位置查找方法)或数字问题(使用类似{{ 3}},也许?)。

4 个答案:

答案 0 :(得分:2)

您可以使用numpy.unpackbits,如下所示,从此表单的ndarray开始:

In [1]: x = np.array([[0b11101110], [0b11111101]], dtype=np.uint8)

In [2]: x
Out[2]:
array([[238],
       [253]], dtype=uint8)

In [3]: df = pd.DataFrame(np.unpackbits(x, axis=1))

In [4]: df.columns = df.columns[::-1]

In [5]: df
Out[5]:
   7  6  5  4  3  2  1  0
0  1  1  1  0  1  1  1  0
1  1  1  1  1  1  1  0  1

然后从DataFrame中,只需stack并找到零:

In [6]: s = df.stack()

In [7]: s.index.names = ['row', 'bit']

In [8]: s[s == 0]
Out[8]:
row  bit
0    4      0
     0      0
1    1      0
dtype: uint8

我认为这是一种相当有效的方法。

答案 1 :(得分:1)

一个好的解决方案是将输入分成小块并在备忘录查找表中使用它(在第一次计算时)。

,例如,如果每个数字/数组是128位;将其分成八个16位的部分,这些部分在表格中查找。在最坏的情况下,查找表需要2个 16 ~65536个条目 - 但是如果零非常稀疏(例如,在任何8个比特组中最多只有两个零,则仅需要约64个)。根据稀疏程度的不同,你可以增加大块的大小。

答案 2 :(得分:1)

在“yuck”部门,我想进入以下选手:

def numpyToBinString(numpyValue):
    return "".join( [str((numpyValue[0] >> shiftLength) & 1 ) for shiftLength in range(numpyValue.dtype.itemsize * 8)] )

适用于shape(,)ndArrays,但可以使用@vectorize装饰器进行扩展。

答案 3 :(得分:0)

您可以使用查找表。

创建一个表,对于0-255中的每个数字都有0个位置,并且有一个访问它的函数,称之为zeroBitPositions,这将返回一个列表。

然后,假设您将数字存储为python long类型(我相信它具有无限精度)。您可以执行以下操作:

allZeroPositions = []
shift = 0
while (num >> shift) > 0:
    zeroPositions += [x + shift for x in zeroBitPositions ((num >> shift) & 0xFF)]
    shift += 8

希望这是一个好的开始。