2016-02-24 14 views
5

Come posso leggere una matrice numpy da una stringa? prendere una stringa come:come leggere l'array 2D numpy dalla stringa?

[[ 0.5544 0.4456], [ 0.8811 0.1189]] 

e convertirlo in un array:

a = from_string("[[ 0.5544 0.4456], [ 0.8811 0.1189]]") 

dove a diventa l'oggetto: np.array([[0.5544, 0.4456], [0.8811, 0.1189]])

aggiornamento:

sto cercando un'interfaccia molto semplice un modo per convertire matrici 2D (di carri) in una stringa e poi un modo per leggere indietro per ricostruire l'array:

arr_to_string(array([[0.5544, 0.4456], [0.8811, 0.1189]])) dovrebbe restituire "[[ 0.5544 0.4456], [ 0.8811 0.1189]]"

string_to_arr("[[ 0.5544 0.4456], [ 0.8811 0.1189]]") dovrebbe restituire l'oggetto array([[0.5544, 0.4456], [0.8811, 0.1189]])

idealmente sarebbe bello se lo arr_to_string avesse un parametro di precisione che controllasse la precisione dei punti mobili convertiti in stringhe, in modo da non ottenere voci come 0.4444444999999999999999999.

non c'è nulla che possa trovare in numpy docs che funzioni in entrambi i modi. np.save vi permette di effettuare una stringa, ma allora non c'è modo per caricarlo indietro nel (np.load funziona solo per i file.)

+0

'json.loads' e' json.dumps' potrebbero essere utili – reptilicus

+0

Riporto indietro, non ho visto le virgole mancanti negli array ... – reptilicus

+0

sto fondamentalmente cercando l'inverso di '' np.array_str'' (http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.array_str.html) ma non riesco a trovarlo – mvd

risposta

6

La sfida è salvare non solo il buffer di dati, ma anche la forma e il dtype. np.fromstring legge il buffer di dati, ma come un array 1d; devi ottenere il dtype e la forma da altro dove.

In [184]: a=np.arange(12).reshape(3,4) 

In [185]: np.fromstring(a.tostring(),int) 
Out[185]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) 

In [186]: np.fromstring(a.tostring(),a.dtype).reshape(a.shape) 
Out[186]: 
array([[ 0, 1, 2, 3], 
     [ 4, 5, 6, 7], 
     [ 8, 9, 10, 11]]) 

Una volta meccanismo onorato di salvare gli oggetti Python è pickle, e numpy è salamoia compatibile:

In [169]: import pickle 

In [170]: a=np.arange(12).reshape(3,4) 

In [171]: s=pickle.dumps(a*2) 

In [172]: s 
Out[172]: "cnumpy.core.multiarray\n_reconstruct\np0\n(cnumpy\nndarray\np1\n(I0\ntp2\nS'b'\np3\ntp4\nRp5\n(I1\n(I3\nI4\ntp6\ncnumpy\ndtype\np7\n(S'i4'\np8\nI0\nI1\ntp9\nRp10\n(I3\nS'<'\np11\nNNNI-1\nI-1\nI0\ntp12\nbI00\nS'\\x00\\x00\\x00\\x00\\x02\\x00\\x00\\x00\\x04\\x00\\x00\\x00\\x06\\x00\\x00\\x00\\x08\\x00\\x00\\x00\\n\\x00\\x00\\x00\\x0c\\x00\\x00\\x00\\x0e\\x00\\x00\\x00\\x10\\x00\\x00\\x00\\x12\\x00\\x00\\x00\\x14\\x00\\x00\\x00\\x16\\x00\\x00\\x00'\np13\ntp14\nb." 

In [173]: pickle.loads(s) 
Out[173]: 
array([[ 0, 2, 4, 6], 
     [ 8, 10, 12, 14], 
     [16, 18, 20, 22]]) 

C'è una funzione NumPy in grado di leggere la stringa salamoia:

In [181]: np.loads(s) 
Out[181]: 
array([[ 0, 2, 4, 6], 
     [ 8, 10, 12, 14], 
     [16, 18, 20, 22]]) 

È menzionato np.save a una stringa, ma non è possibile utilizzare np.load. Un modo per aggirare ulteriormente il codice e utilizzare np.lib.npyio.format.

In [174]: import StringIO 

In [175]: S=StringIO.StringIO() # a file like string buffer 

In [176]: np.lib.npyio.format.write_array(S,a*3.3) 

In [177]: S.seek(0) # rewind the string 

In [178]: np.lib.npyio.format.read_array(S) 
Out[178]: 
array([[ 0. , 3.3, 6.6, 9.9], 
     [ 13.2, 16.5, 19.8, 23.1], 
     [ 26.4, 29.7, 33. , 36.3]]) 

La stringa save ha un'intestazione con dtype e shape informazioni:

In [179]: S.seek(0) 

In [180]: S.readlines() 
Out[180]: 
["\x93NUMPY\x01\x00F\x00{'descr': '<f8', 'fortran_order': False, 'shape': (3, 4), }   \n", 
'\x00\x00\x00\x00\x00\x00\x00\x00ffffff\n', 
'@ffffff\[email protected]\xcc\xcc\xcc\xcc\xcc\xcc#@ffffff*@\x00\x00\x00\x00\x00\[email protected]\xcc\xcc\xcc\xcc\xcc\[email protected]\x99\x99\x99\x99\x99\[email protected]:@33333\[email protected]\x00\x00\x00\x00\x00\[email protected]@fffff&[email protected]'] 

Se si desidera una stringa leggibile, si potrebbe provare json.

In [196]: import json 

In [197]: js=json.dumps(a.tolist()) 

In [198]: js 
Out[198]: '[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]' 

In [199]: np.array(json.loads(js)) 
Out[199]: 
array([[ 0, 1, 2, 3], 
     [ 4, 5, 6, 7], 
     [ 8, 9, 10, 11]]) 

Andando da/per la rappresentazione della lista della matrice è l'uso più evidente di json. Qualcuno potrebbe aver scritto una rappresentazione più elaborata di array json.

Si potrebbe anche percorrere il percorso di formato csv - ci sono state molte domande sulla lettura/scrittura di array CSV.


'[[ 0.5544 0.4456], [ 0.8811 0.1189]]' 

è una rappresentazione di stringa povero per questo scopo. Assomiglia molto allo str() di un array, ma con , anziché \n. Ma non c'è un modo pulito di analizzare il nidificato [], e il delimitatore mancante è un dolore. Se utilizza costantemente , allora json può convertirlo in elenco.

np.matrix accetta un MATLAB come stringa:

In [207]: np.matrix(' 0.5544, 0.4456;0.8811, 0.1189') 
Out[207]: 
matrix([[ 0.5544, 0.4456], 
     [ 0.8811, 0.1189]]) 

In [208]: str(np.matrix(' 0.5544, 0.4456;0.8811, 0.1189')) 
Out[208]: '[[ 0.5544 0.4456]\n [ 0.8811 0.1189]]' 
+0

Che risposta sofisticata e completa! Pickle è la scelta migliore qui Avevo anche bisogno di trasferire array 2dim float piuttosto grandi via AMQP e pickle ha fatto il lavoro (anche senza json). Grazie mille! – Sauer

0

Numpy fornisce la funzione fromstring per questo scopo. Funziona con binario o ascii.

http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.fromstring.html

+1

no, funziona solo per l'array 1-D. Non riesce per il mio esempio: '' np.fromstring ("[[0.5544 0.4456], [0.8811 0.1189]] ")' 'fornisce' 'ValueError: la dimensione della stringa deve essere un multiplo della dimensione dell'elemento'' – mvd

+0

Bene inoltre puoi' eval' elencare la stringa e chiamare il costruttore np.array, ad esempio 'arr = np.array (eval (lst_str)) '. Non l'ho messo in risposta a causa dell'alto livello di sospetto riguardante' eval' –

+0

Abbastanza sicuro che ci sia un modo 'fromstring' può farlo ... proverò quando arriverò alla mia scrivania però –

2

io non sono sicuro che c'è un modo semplice per fare questo, se non si dispone di virgole tra i numeri nelle liste interne, ma se lo fai, allora è possibile utilizzare ast.literal_eval:

import ast 
import numpy as np 
s = '[[ 0.5544, 0.4456], [ 0.8811, 0.1189]]' 
np.array(ast.literal_eval(s)) 

array([[ 0.5544, 0.4456], 
     [ 0.8811, 0.1189]]) 

EDIT: non ho provato molto, ma si potrebbe usare re per inserire le virgole dove ti serve:

import re 
s1 = '[[ 0.5544 0.4456], [ 0.8811 -0.1189]]' 
# Replace spaces between numbers with commas: 
s2 = re.sub('(\d) +(-|\d)', r'\1,\2', s1) 
s2 
'[[ 0.5544,0.4456], [ 0.8811,-0.1189]]' 

e poi a mano o n per ast.literal_eval:

np.array(ast.literal_eval(s2)) 
array([[ 0.5544, 0.4456], 
     [ 0.8811, -0.1189]]) 

(è necessario essere attenti a corrispondere spazi tra le cifre, ma anche gli spazi tra una cifra un segno meno).

+0

non ho virgole tra i numeri, solo spazi – mvd

+0

@mvd Potresti provare la mia modifica, ma non l'ho provata a fondo – xnx

0

avanti a stringa:

import numpy as np 
def array2str(arr, precision=None): 
    s=np.array_str(arr, precision=precision) 
    return s.replace('\n', ',') 

Backward a matrice:

import re 
import ast 
import numpy as np 
def str2array(s): 
    # Remove space after [ 
    s=re.sub('\[ +', '[', s.strip()) 
    # Replace commas and spaces 
    s=re.sub('[,\s]+', ', ', s) 
    return np.array(ast.literal_eval(s)) 

Se si utilizza repr() convertire array stringhe, la conversione sarà banale.