Чтение элементов unicode в массив numpy
рассмотрим текстовый файл под названием "new.txt", содержащий следующие элементы:
μm
∂r
∆λ
в Python 2.7, я могу прочитать файл, вписав:
>>> import codecs
>>> f = codecs.open('new.txt', encoding='utf-8')
>>> lines = [line.strip() for line in f2.readlines()]
>>> lines
[u'u03bcm', u'u2202r', u'u2206u03bb']
>>> print lines[0]
μm
пока все хорошо. Я могу легко преобразовать этот список в массив numpy через:
>>> import numpy as np
>>> arr = np.array(lines)
>>> arr
array([u'u03bcm', u'u2202r', u'u2206u03bb'],
dtype='<U2')
проблема в том, что я не могу прочитать этот файл напрямую через функцию loadtxt 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)
как правильно читать этот файл в numpy напрямую?
спасибо.
2 ответов
в памяти строки Юникода представлены как UCS-2 или UCS-4 в зависимости от того, как интерпретатор Python был составлен. Ваш файл закодирован в UTF-8, поэтому вам нужно перекодировать его, прежде чем вы сможете сопоставить его с массивом NumPy. loadtxt()
не могу сделать перекодирование для вас-в конце концов NumPy в основном ориентирован на числовые массивы.
предполагая, что каждая строка имеет одинаковое количество символов, вы также можете использовать более эффективный вариант
s = codecs.open("new.txt", encoding="utf-8").read()
arr = numpy.frombuffer(s, dtype="<U3")
это будет включать символы новой строки в строки. Чтобы не включать их, используйте
arr = numpy.frombuffer(s.replace("\n", ""), dtype="<U2")
редактировать: если строки вашего файла имеют разную длину, и вы хотели бы избежать промежуточного списка, вы можете использовать
arr = numpy.fromiter(codecs.open("new.txt", encoding="utf-8"), dtype="<U2")
Я не уверен, что это будет внутренне создавать какой-то временный список.
если вы хотите использовать loadtxt
, вы можете либо сначала загрузить массив необработанных байтов, а затем декодировать:
data = np.loadtxt('foo.txt', dtype='S8')
unicode_data = data.view(np.chararray).decode('utf-8')
или укажите преобразователь для декодирования:
data = np.loadtxt('foo.txt', converters={0: lambda x: unicode(x, 'utf-8')}, dtype='U2')
, используя fromiter
как и в ответе Свена, вероятно, будет более эффективным, чем loadtxt
.