2011-06-16 14 views
9

Considere un archivo de texto llamado "nuevo.txt" que contiene los siguientes elementos:elementos Unicode de lectura en una matriz numpy

μm 
∂r 
∆λ 

En Python 2.7, puedo leer el archivo escribiendo:

>>> import codecs 
>>> f = codecs.open('new.txt', encoding='utf-8') 
>>> lines = [line.strip() for line in f2.readlines()] 
>>> lines 
[u'\u03bcm', u'\u2202r', u'\u2206\u03bb'] 
>>> print lines[0] 
μm 

Hasta aquí todo bien. Puedo convertir fácilmente esta lista a un conjunto numpy a través de:

>>> import numpy as np 
>>> arr = np.array(lines) 
>>> arr 
array([u'\u03bcm', u'\u2202r', u'\u2206\u03bb'], 
     dtype='<U2') 

La cuestión es que no puede leer este archivo directamente a través de la función loadtxt de numpy:

>>> np.loadtxt('new.txt', dtype=np.unicode_) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib64/python2.7/site-packages/numpy/lib/npyio.py", line 805, in loadtxt 
    X = np.array(X, dtype) 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xce in position 0: ordinal not in range(128) 

¿Cuál es la forma correcta de leer este archivo en numpy directamente?

Gracias.

Respuesta

8

En memoria, las cadenas de unicode se representan como UCS-2 o UCS-4, dependiendo de cómo se compiló su intérprete de Python. Su archivo está codificado en UTF-8, por lo que debe volver a codificarlo antes de poder asignarlo a la matriz NumPy. loadtxt() no puede hacer la recodificación por usted; después de todo, NumPy está principalmente dirigido a matrices numéricas.

Suponiendo que cada línea tiene el mismo número de caracteres, también se puede utilizar la variante más eficiente

s = codecs.open("new.txt", encoding="utf-8").read() 
arr = numpy.frombuffer(s, dtype="<U3") 

Esto incluirá los caracteres de nueva línea en las cuerdas. Para no incluirlos, utilice

arr = numpy.frombuffer(s.replace("\n", ""), dtype="<U2") 

Editar: Si las líneas de su archivo tienen diferentes longitudes y que le gustaría evitar la lista intermedia, puede utilizar

arr = numpy.fromiter(codecs.open("new.txt", encoding="utf-8"), dtype="<U2") 

No estoy Sin embargo, si esto creará internamente alguna lista temporal.

+1

+1 - pero una nota: puede pasar un archivo abierto directamente a 'loadtxt', y para mí, abrir el archivo con' codecs.open' y pasarlo a 'loadtxt' resolvió el problema. ¡O más bien un problema similar, ya que mi 'loadtxt' no tenía ningún problema con un archivo utf-8! – senderle

+0

@senderle: Extraño: no funciona para mí. Estoy usando NumPy 1.5.1 aquí - tal vez esto importe. –

+0

¿Tiene esto algo que ver con el uso del puerto numpy Python 3 ?. Todavía obtengo UnicodeEncodeError en my numpy, que funciona bajo Python 2.7. –

2

Si desea utilizar loadtxt, puede primera carga de la matriz de bytes en bruto y luego decodificar:

data = np.loadtxt('foo.txt', dtype='S8') 
unicode_data = data.view(np.chararray).decode('utf-8') 

o especificar un convertidor para la decodificación:

data = np.loadtxt('foo.txt', converters={0: lambda x: unicode(x, 'utf-8')}, dtype='U2') 

Sin embargo, el uso de fromiter como en la respuesta de Sven es probable que sea más eficaz que loadtxt.

Cuestiones relacionadas