Список кортежей в массив numpy - смешанные типы, преобразование юникода не работает

У меня есть список кортежей в формате «текст, целое число», где текст имеет юникод и исходит из файла, открытого с кодировкой utf-8.

Я пытаюсь преобразовать список в многомерный массив numpy с правильными типами.

Используя обычные np.array или np.asarray, преобразует все в Unicode или U1

tuples = [("A",1),("B",2)]
np.array(tuples)
>>> [['A' '1']
    ['B' '2']]

Указание типов, которые я хочу, дает мне пустую строку, а не многомерную:

np.array(tuples, dtype=np.dtype("U,int"))
>>> [('', 1) ('', 2)]

Если я не укажу количество символов в юникоде, чего я не могу сделать, потому что мой текст имеет переменную длину. Также это не многомерно.

np.array(tuples, dtype=np.dtype("<U99,int"))
>>> [('A', 1) ('B', 2)]

Как я могу преобразовать свой список кортежей в массив numpy с целочисленным и строковым форматом? Кроме того, в конечном итоге я буду делать np.where() во втором столбце и проверять, больше ли значение, чем, например. 50, поэтому решение, которое работает со следующим шагом, было бы идеальным. Спасибо!

edit: в идеале результатом должен быть многомерный массив, чтобы при необходимости отдельные столбцы можно было выбирать самостоятельно.


person Lobstw    schedule 18.06.2018    source источник
comment
Возможный дубликат строк numpy recarray переменной длины   -  person AGN Gazer    schedule 18.06.2018
comment
Также см. другой связанный вопрос: stackoverflow.com/q/1664917/8033585   -  person AGN Gazer    schedule 18.06.2018
comment
Почему вы хотите, чтобы он был многомерным? Первым измерением будут записи. Именованные поля заменяют столбцы обычного двумерного массива.   -  person hpaulj    schedule 18.06.2018
comment
@hpaulj Я подумал, что позже будет проще использовать np.where для выбора нужных строк, если массив был многомерным. В противном случае это одномерный массив кортежей, и я не могу получить доступ к первому значению каждого кортежа, не сделав сначала копию, например array[:,0]   -  person Lobstw    schedule 18.06.2018


Ответы (2)


Нетрудно выбрать разумную длину строки Unicode.

In [172]: alist = [('A',1),('Beta', 2), ('Gamma', 3)]

например, чтобы получить длину строк в списке:

In [173]: dt1 = np.array([row[0] for row in alist]).dtype
In [174]: dt1
Out[174]: dtype('<U5')
In [175]: dt = np.dtype([('label',dt1),('value', int)])
In [176]: dt
Out[176]: dtype([('label', '<U5'), ('value', '<i8')])

In [177]: arr = np.array(alist, dt)
In [178]: arr
Out[178]: 
array([('A', 1), ('Beta', 2), ('Gamma', 3)],
      dtype=[('label', '<U5'), ('value', '<i8')])

использовать поля имени:

In [179]: arr['label']
Out[179]: array(['A', 'Beta', 'Gamma'], dtype='<U5')
In [180]: arr['value']%2==1
Out[180]: array([ True, False,  True])

Обычно нам не нужен многомерный структурированный массив.

Если данные находятся в файле стиля csv, мы можем позволить genfromtxt выбрать размер строкового поля:

In [181]: txt = """A 1
     ...: Beta 2
     ...: Gamma 3"""
In [182]: data = np.genfromtxt(txt.splitlines(), dtype=None,encoding=None)
In [183]: data
Out[183]: 
array([('A', 1), ('Beta', 2), ('Gamma', 3)],
      dtype=[('f0', '<U5'), ('f1', '<i8')])
person hpaulj    schedule 18.06.2018
comment
Нет ли способа сделать это как многомерный массив? Таким образом, я мог легко выбрать все буквы первого столбца, если захочу, или все значения второго столбца по отдельности. Потому что таким образом мне пришлось бы перебирать массив и разделять кортежи, используя понимание списка или подобное, если бы они мне понадобились. - person Lobstw; 18.06.2018
comment
Я показал, как выбрать строковое поле и числовое. Возможно, вам придется прочитать о структурированных массивах. - person hpaulj; 18.06.2018
comment
Извините за это, я перепутал поля имени с чем-то другим. Это хорошо ответило на мой вопрос, спасибо. Небольшой вопрос, есть ли разница между установкой dtype на int и np.dtype("int") - person Lobstw; 18.06.2018

Как предлагается в связанных вопросах (строки numpy recarray переменной длины, Автоматическая длина строки в переназначении), объявите первый тип как object:

np.array([("A", 1), ("B", 2)], dtype=[('str', np.object), ('int', np.int)])
person AGN Gazer    schedule 18.06.2018