【问题标题】:efficiently find bit positions in binary strings in a numpy array有效地查找 numpy 数组中二进制字符串中的位位置
【发布时间】:2013-06-06 17:17:48
【问题描述】:

我有一个包含二进制字符串(0 和 1)的大型 Pandas 数据框(大多数情况下是 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 )

屈服zero_positions =...

         value
row bit
0   4        0
    0        0
1   1        0

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

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

【问题讨论】:

  • 如果您只是在字节中查找零位,为什么不使用查找表?
  • 好点,@gnibbler。实际上,我真正想要使用的输入字符串要长得多(128 位),这使得查找表变得不切实际。

标签: python string numpy binary pandas


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    您可以使用查找表。

    创建一个表,其中包含从 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
    

    希望这是一个好的开始。

    【讨论】:

      【解决方案3】:

      您可以按如下方式使用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
      

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

      【讨论】:

      • 这很好用,尽管numpy.unpackbits 似乎只适用于 8 位整数。我不确定将 128 位整数存储在 ndarray 中的最佳方法,更不用说将它们转换为 8 位块(使用 np.frombuffer 会引入一些字节序问题)。现在我在想,我的真正的问题可能更多在于我如何将这些大的位串放入 Pandas,而不是我之后如何解析它们......
      • @Dan 这很烦人,它是一个优雅的解决方案(适用于 uint8s)......:s
      【解决方案4】:

      在“恶心”部门,我想报名以下选手:

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

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

      【讨论】:

      • 作为后续,您似乎想玩 bitArray 包。
      猜你喜欢
      • 2017-06-28
      • 2021-06-11
      • 1970-01-01
      • 2015-08-03
      • 2019-06-14
      • 1970-01-01
      • 2016-06-10
      • 2019-09-28
      相关资源
      最近更新 更多