2014-12-16 3 views
7

Quindi ho quello che sento è un problema molto stupido.Cercando di strip b '' dal mio array Numpy

ho creare una matrice da un file:

A1=np.loadtxt(file, dtype='a100') 

voglio scrivere che matrice dopo che è fatto di elaborazione ad un altro file:

np.savetxt("Test.txt", A1, fmt=%s, delimiter=',') 

Perché è scrivendo b'string '? Penso di capire che lo stia scrivendo come byte ma per la vita di me non riesco a capire come scriverlo senza la b ''.

So che probabilmente è qualcosa di incredibilmente semplice che sto trascurando!

+4

Hai un bytearray. guarda http://stackoverflow.com/questions/606191/convert-bytes-to-a-python-string –

+0

Grazie, darò un'occhiata. C'è qualcosa che posso fare per la parte in formato di testo per ripararlo? – user2624599

risposta

2

A1 viene caricato come una matrice di bytestrings. Python3 usava le stringhe unicode come default, quindi di solito le prepone con la 'b'. Questo è normale con print. Sono un po 'sorpreso che lo faccia anche durante la scrittura del file.

In ogni caso, questo sembra fare il trucco:

A2=np.array([x.decode() for x in A1]) 
np.savetxt("Test.txt", A2, fmt='%s', delimiter=',') 

A2 avrà un DTYPE come dtype='<U100'.


La mia serie di test è:

array([b'one.com', b'two.url', b'three.four'], dtype='|S10') 

caricato da un file di testo semplice:

one.com 
two.url 
three.four 

.decode è un metodo di stringa. [x.decode() for x in A1] funziona per un semplice array 1d di bytestrings. Se A1 è 2d, l'iterazione deve essere eseguita su tutti gli elementi, non solo sulle righe. E se A1 è array strutturato, deve essere applicato alle stringhe all'interno degli elementi.


Un'altra possibilità è quella di utilizzare un convertitore durante il carico, in modo da ottenere una serie di (Unicode) stringhe

In [508]: A1=np.loadtxt('urls.txt', dtype='U', 
    converters={0:lambda x:x.decode()}) 
In [509]: A1 
Out[509]: 
array(['one.com', 'two.url', 'three.four'], dtype='<U10') 
In [510]: np.savetxt('test0.txt',A1,fmt='%s') 
In [511]: cat test0.txt 
one.com 
two.url 
three.four 

Il lib che contiene loadtxt ha un paio di funzioni di conversione, asbytes, asbytes_nested, e asstr. Quindi converters potrebbe anche essere: converters={0:np.lib.npyio.asstr}.

genfromtxt gestisce questo senza converters:

A1=np.genfromtxt('urls.txt', dtype='U') 
# array(['one.com', 'two.url', 'three.four'], dtype='<U10') 

Per comprendere il motivo per cui savetxt Salva stringhe Unicode come vogliamo, ma aggiunge il b per stringhe di byte, dobbiamo guardare al suo codice.

np.savetxt (in esecuzione su PY3) è essenzialmente:

fh = open(fname, 'wb') 
X = np.atleast_2d(X).T 
# make a 'fmt' that matches the columns of X (with delimiters) 
for row in X: 
    fh.write(asbytes(format % tuple(row) + newline)) 

Guardando due stringhe di esempio (str e bytestr):

In [617]: asbytes('%s'%tuple(['one.two'])) 
Out[617]: b'one.two' 

In [618]: asbytes('%s'%tuple([b'one.two'])) 
Out[618]: b"b'one.two'" 

scrittura su un file 'wb' rimuove quello strato esterno b'', lasciando l'interno per il test. Spiega anche perché le stringhe ('plain' py3 unicode) sono scritte come stringhe 'latin1' nel file.


si potrebbe scrivere un array di stringhe di byte direttamente, senza savetxt. Ad esempio:

A0 = array([b'one.com', b'two.url', b'three.four'], dtype='|S10') 
with open('test0.txt','wb') as f: 
    for x in A0: 
     f.write(x+b'\n') 

cat test0.txt 
    one.com 
    two.url 
    three.four 

stringhe Unicode possono anche essere scritte direttamente, producendo lo stesso file:

A1 = array(['one.com', 'two.url', 'three.four'], dtype='<U10') 
with open('test1.txt','w') as f: 
    for x in A1: 
     f.write(x+'\n') 

La codifica predefinita per un file è encoding='UTF-8', lo stesso utilizzato con 'one.com'.encode(). L'effetto è lo stesso di quello che fa savetxt:

with open('test1.txt','wb') as f: 
    for x in A1: 
     f.write(x.encode()+b'\n') 

np.char ha .encode e .decode metodi, che sembrano operare iterativamente sugli elementi di un array.

Così

np.char.decode(A1) # convert |S10 to <U10, like [x.decode() for x in A1] 
np.char.encode(A1) # convert <U10 to |S10 

Questo funziona con array multidimensionali

np.savetxt('testm.txt',np.char.decode(A_bytes[:,None][:,[0,0]]), 
    fmt='%s',delimiter=', ') 

Con una matrice strutturata, np.char.decode deve essere applicati singolarmente per ciascuno dei campi char.

+0

Ho provato il tuo e questo è quello che ho ricevuto come errore: L'oggetto '' numpy.void 'non ha attributo' decode'' – user2624599

+0

Qual è il dtype di 'A1'? Se 'x' è un' numpy.void', suppongo che sia un elemento di una matrice strutturata. '.decode' è un metodo' stringa'. – hpaulj