gpt4 book ai didi

python - 如何将整数数组转换为特定长度的二进制数组

转载 作者:太空宇宙 更新时间:2023-11-03 13:55:56 25 4
gpt4 key购买 nike

我正在尝试将一个 numpy 整数数组(比方说 A=[3,5,2])转换为一个具有最低有效位优先格式和特定​​长度的 numpy 二进制数组。也就是说,长度为 6 的结果应该如下所示:

A' = [1 1 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0]

前 6 个值用于 A 的第一个元素,后 6 个值用于 A 的第二个元素,最后 6 个值用于最后一个A 的元素。

我目前的解决方案如下:

np.multiply( np.delete( np.unpackbits( np.abs(A.astype(int)).view("uint8")).reshape(-1,8)[:,::-1].reshape(-1,64), np.s_[ln::],1).astype("float64").ravel(), np.repeat(np.sign(A), ln))

其中 ln 表示具体的 ln(在示例中为 6)

有没有更快的方法来做到这一点?

提前致谢。

编辑: 我早该指出。 A 也可以有负值。例如,如果 A=[-11,5]ln=6,则返回的数组应该是:

A'=[-1 -1 0 -1 0 0 1 0 1 0 0 0]

请注意,ln=6 只是一个示例。甚至可能是 60。

很抱歉遗漏了这部分要求。

最佳答案

这是一个矢量化的 -

((A[:,None] & (1 << np.arange(ln)))!=0).ravel().view('i1')

另一个带有 np.unpackbits -

np.unpackbits(A.view(np.uint8)[::8]).reshape(-1,8)[:,ln-7:1:-1].ravel()

sample 运行-

In [197]: A
Out[197]: array([3, 5, 2])

In [198]: ln = 6

In [199]: ((A[:,None] & (1 << np.arange(ln)))!=0).ravel().view('i1')
Out[199]: array([1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0], dtype=int8)

In [200]: np.unpackbits(A.view(np.uint8)[::8]).reshape(-1,8)[:,ln-7:1:-1].ravel()
Out[200]: array([1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0], dtype=uint8)

大型阵列上的计时 -

In [201]: A = np.random.randint(0,6,1000000)

In [202]: ln = 6

In [203]: %timeit ((A[:,None] & (1 << np.arange(ln)))!=0).ravel().view('i1')
10 loops, best of 3: 32.1 ms per loop

In [204]: %timeit np.unpackbits(A.view(np.uint8)[::8]).reshape(-1,8)[:,ln-7:1:-1].ravel()
100 loops, best of 3: 8.14 ms per loop

如果您可以接受 2D 数组输出,其中每一行都包含输入中每个元素的二进制信息,那就更好了 -

In [205]: %timeit np.unpackbits(A.view(np.uint8)[::8]).reshape(-1,8)[:,ln-7:1:-1]
1000 loops, best of 3: 1.04 ms per loop

其他发布的方法-

# @aburak's soln
In [206]: %timeit np.multiply( np.delete( np.unpackbits( np.abs(A.astype(int)).view("uint8")).reshape(-1,8)[:,::-1].reshape(-1,64), np.s_[ln::],1).astype("float64").ravel(), np.repeat(np.sign(A), ln))
10 loops, best of 3: 180 ms per loop

# @Jacques Gaudin's soln
In [208]: %timeit np.array([int(c) for i in A for c in np.binary_repr(i, width=6)[::-1]])
1 loop, best of 3: 3.34 s per loop

# @Paul Panzer's soln
In [209]: %timeit np.unpackbits(A[:, None].view(np.uint8)[..., ::-1] if sys.byteorder=='little' else A[:, None].view(np.uint8), axis=-1)[..., :-ln-1:-1].reshape(-1)
10 loops, best of 3: 35.4 ms per loop

这篇文章中支持第二种方法的最好的事情是我们有一个 uint8 输入的 dtype 版本,它只是输入的一个 View ,因此内存效率高 -

In [238]: A
Out[238]: array([3, 5, 2])

In [239]: A.view(np.uint8)[::8]
Out[239]: array([3, 5, 2], dtype=uint8)

In [240]: np.shares_memory(A,A.view(np.uint8)[::8])
Out[240]: True

因此,当我们使用 np.unpackbits 时,我们输入的元素数量与原始元素数量相同。

此外,A.view(np.uint8)[::8] 似乎是将 int dtype 数组视为 uint8< 的好技巧一个!


为了解决一般情况,我们可以扩展前面列出的方法。

方法 #1(ln 高达 63):

(((np.abs(A)[:,None] & (1 << np.arange(ln)))!=0)*np.sign(A)[:,None]).ravel()

方法 #2:

a = np.abs(A)
m = ((ln-1)//8)+1
b = a.view(np.uint8).reshape(-1,8)[:,:m]
U = np.unpackbits(b,axis=1)
out = U.reshape(-1,m,8)[...,::-1].reshape(len(A),-1)[...,:ln]
out = (out*np.sign(A)[:,None]).ravel()

关于python - 如何将整数数组转换为特定长度的二进制数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55633755/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com