2 votes

Méthode pythique pour convertir une liste d'int32 signés en tableau numpy binaire/booléen

Existe-t-il un meilleur moyen (plus efficace et/ou plus lisible) de convertir un int32 signé en tableau numpy binaire/booléen transposé ?

Cet exemple est une simplification. fp peut comporter près de 1 000 éléments

Voici ce que j'ai obtenu jusqu'à présent (en utilisant Python 2.7) :

fp = [-15707075, -284140225]
np.transpose(np.array([[b == '1' for b in list('{:32b}'.format(i & 0xffffffff))] for i in fp]))

Résultat :

[[ True  True]
 [ True  True]
 [ True  True]
 [ True False]
 [ True  True]
 [ True  True]
 [ True  True]
 [ True  True]
 [False False]
 [False False]
 [False False]
 [ True  True]
 [False False]
 [False False]
 [False False]
 [False False]
 [False False]
 [ True  True]
 [False False]
 [ True  True]
 [False  True]
 [ True  True]
 [False False]
 [False  True]
 [False False]
 [False False]
 [ True  True]
 [ True  True]
 [ True  True]
 [ True  True]
 [False  True]
 [ True  True]]

3voto

unutbu Points 222216

Utilisation de numpy.unpackbits est plus rapide si fp est un grand tableau NumPy :

(np.unpackbits(fp.astype('>i4').view('4,uint8'), axis=1).T.astype(bool))

astype('>i4') convertit fp dans un tableau d'ints 32 bits big-endian, puis view('4,uint8') voit (ou, on pourrait peut-être dire, réinterprète) l'image 32 bits de l'utilisateur. comme quatre ints de 8 bits. Ceci est fait puisque unpackbits s'attend à un tableau de ints 8 bits non signés. Le format big-endian est utilisé pour s'assurer que les bits les plus importants les bits les plus significatifs se trouvent à gauche, ce qui permet d'organiser les valeurs de la manière suivante np.unpackbits retourne le bits dans l'ordre souhaité.

In [280]: fp = np.array([-15707075, -284140225])

In [281]: fp.astype('>i4').view('4,uint8')
Out[281]: 
array([[255,  16,  84,  61],
       [239,  16,  93,  63]], dtype=uint8)

In [282]: np.unpackbits(fp.astype('>i4').view('4,uint8'), axis=1)
Out[282]: 
array([[1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1,
        0, 0, 0, 0, 1, 1, 1, 1, 0, 1],
       [1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1,
        0, 1, 0, 0, 1, 1, 1, 1, 1, 1]], dtype=uint8)

import numpy as np

fp = np.array([-15707075, -284140225])
expected = (np.transpose(np.array([[b == '1' for b in list('{:32b}'.format(i & 0xffffffff))] for i in fp])))

result = (np.unpackbits(fp.astype('>i4').view('4,uint8'), axis=1).T.astype(bool))

assert (expected == result).all()

Utilisation de np.unpackbits est environ 72x plus rapide (sur ma machine) pour un tableau de taille 100. La vitesse augmente avec la longueur du tableau fp :

In [241]: fp = np.random.random(size=100).view('int32')

In [276]: %timeit expected = (np.transpose(np.array([[b == '1' for b in list('{:32b}'.format(i & 0xffffffff))] for i in fp])))
100 loops, best of 3: 2.22 ms per loop

In [277]: %timeit result = (np.unpackbits(fp.astype('>i4').view('4,uint8'), axis=1).T.astype(bool))
10000 loops, best of 3: 30.6 µs per loop

0voto

DYZ Points 26904

Non beaucoup meilleur, mais toujours plus pythique :

np.array([list('{:32b}'.format(i & 0xffffffff)) for i in fp]).astype(bool).T

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X