Python 在numpy数组中高效地查找二进制字符串中的位位置

Python 在numpy数组中高效地查找二进制字符串中的位位置,python,string,numpy,binary,pandas,Python,String,Numpy,Binary,Pandas,我有一个包含二进制字符串(0和1)的大熊猫数据帧(大多数情况下是Numpyndarray的子类)。我需要找到这些字符串中所有零的位置,然后标记它们。此外,我希望零的位置相对稀疏(约占所有位位置的1%) 基本上,我想运行这样的程序: import pandas as pd x = pd.Series([ '11101110', '11111101' ], ) # start with strings x = pd.Series([ 0b11101110, 0b11111101 ], ) # ...

我有一个包含二进制字符串(0和1)的大熊猫数据帧(大多数情况下是Numpy
ndarray
的子类)。我需要找到这些字符串中所有零的位置,然后标记它们。此外,我希望零的位置相对稀疏(约占所有位位置的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 )
产生
零位置=

         value
row bit
0   4        0
    0        0
1   1        0
我尝试了几种不同的方法来实现这一点,但没有比一次循环一行更好的方法。(编辑:我要查看的实际字符串比这里的8位示例长得多,因此查找表不起作用。)


我不确定将其作为字符串问题(Pandas不提供子字符串位置查找方法)或数字问题(使用类似的方法,可能?)处理是否更有效。

一个好的解决方案是将输入分割成小块,并在记忆查找表中使用(第一次计算通过的时间)


例如,如果每个数字/数组为128位,则将其分成八个16位部分,在表中查找。最坏情况下,查找表需要216~65536个条目-但如果零非常稀疏(例如,任何8位组中最多两个零只需要约64个)。这取决于块的稀疏程度。

一个好的解决方案是将输入分割成较小的块,并在一个记忆化的查找表中使用它(第一次计算)


例如,如果每个数字/数组为128位,则将其分成八个16位部分,在表中查找。最坏情况下,查找表需要216~65536个条目-但如果零非常稀疏(例如,任何8位组中最多两个零只需要约64个)。这取决于块的稀疏程度。

可以使用查找表

创建一个表,其中0-255之间的每个数字都有0个位置,并有一个访问该表的函数,称之为
zeroBitPositions
,这将返回一个列表

然后,假设您将数字存储为python长类型(我相信它具有无限精度)

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

希望这是一个好的开始。

您可以使用查找表

创建一个表,其中0-255之间的每个数字都有0个位置,并有一个访问该表的函数,称之为
zeroBitPositions
,这将返回一个列表

然后,假设您将数字存储为python长类型(我相信它具有无限精度)

allZeroPositions = []
shift = 0
while (num >> shift) > 0:
    zeroPositions += [x + shift for x in zeroBitPositions ((num >> shift) & 0xFF)]
    shift += 8
希望这是一个好的开始。

您可以使用以下内容,从该表单的数据数组开始:

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
然后从数据帧中,只需找到零:

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
我认为这是一种相当有效的方法。

您可以使用以下方法,从以下表格的数据开始:

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
然后从数据帧中,只需找到零:

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
我认为这是一个相当有效的方法。

在“恶心”部门,我想输入以下参赛者:

def numpyToBinString(numpyValue):
    return "".join( [str((numpyValue[0] >> shiftLength) & 1 ) for shiftLength in range(numpyValue.dtype.itemsize * 8)] )
适用于形状(,)ndArrays,但可以使用@vectorize decorator进行扩展。

在“恶心”部门,我想输入以下参赛者:

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

适用于形状(,)ndArrays,但可以使用@vectorize decorator进行扩展。

如果您只是查找字节中的零位,为什么不使用查找表呢?很好,@gnibler。实际上,我真正想要使用的输入字符串要长得多(128位)使查找表变得不切实际。如果您只是查找字节中的零位,为什么不使用查找表呢?很好,@gnibbler。实际上,我真正想要使用的输入字符串要长得多(128位)使查找表变得不切实际。虽然
numpy.unpackbits
似乎只对8位整数有效,但这很有效。我不确定在
ndarray
中存储128位整数的最佳方法,更不用说将其转换为8位块(使用会引入一些endianness问题).现在我在想,我真正的问题可能更多的是如何将这些大位字符串放入Pandas中,而不是之后如何解析它们…@Dan这很烦人,这是一个优雅的解决方案(适用于uint8s)…:这很好,尽管
numpy.unpackbits
似乎只对8位整数有效。我不确定在
ndarray
中存储128位整数的最佳方法,更不用说将它们转换为8位块了(使用会带来一些endianness方面的问题).现在我在想,我真正的问题可能更多的是如何将这些大位字符串放入Pandas中,而不是之后如何解析它们…@Dan这很烦人,这是一个优雅的解决方案(适用于uint8s)…:作为后续操作,您似乎想玩软件包。作为后续操作,您似乎想玩软件包。