Чтение элементов Юникода в массив numpy - PullRequest
10 голосов
/ 16 июня 2011

Рассмотрим текстовый файл с именем «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'\u2206\u03bb']
>>> print lines[0]
μm

Пока все хорошо. Я могу легко преобразовать этот список в массив с помощью:

>>> import numpy as np
>>> arr = np.array(lines)
>>> arr
array([u'\u03bcm', u'\u2202r', u'\u2206\u03bb'], 
      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 ]

10 голосов
/ 16 июня 2011

В памяти строки Unicode представлены как 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")

Я не уверен, что это создаст внутренний временный список.

2 голосов
/ 17 июня 2011

Если вы хотите использовать 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...