Другой вариант - создать структурированный массив со смесью целочисленных и строковых полей.
In [252]: import numpy.lib.recfunctions as rf
In [258]: X = [[3, 'aa', 10],
...: [1, 'bb', 22],
...: [2, 'cc', 28],
...: [5, 'bb', 32],
...: [4, 'cc', 32]]
In [259]: dt = np.dtype('i,U10,i')
In [260]: dt
Out[260]: dtype([('f0', '<i4'), ('f1', '<U10'), ('f2', '<i4')])
В недавнем (1.16) numpy есть функция, которая преобразует неструктурированные массивы (например, строку dtype) в структурированные.:
In [261]: Y = rf.unstructured_to_structured(np.array(X), dt)
In [262]: Y
Out[262]:
array([(3, 'aa', 10), (1, 'bb', 22), (2, 'cc', 28), (5, 'bb', 32),
(4, 'cc', 32)],
dtype=[('f0', '<i4'), ('f1', '<U10'), ('f2', '<i4')])
Доступ к полям осуществляется по имени:
In [264]: Y['f0']
Out[264]: array([3, 1, 2, 5, 4], dtype=int32)
In [265]: Y['f1']
Out[265]: array(['aa', 'bb', 'cc', 'bb', 'cc'], dtype='<U10')
Преобразование X
в список кортежей будет работать так же хорошо
In [266]: np.array([tuple(row) for row in X], dtype=dt)
Out[266]:
array([(3, 'aa', 10), (1, 'bb', 22), (2, 'cc', 28), (5, 'bb', 32),
(4, 'cc', 32)],
dtype=[('f0', '<i4'), ('f1', '<U10'), ('f2', '<i4')])
Объектмассив и структурированный массив каждый имеет свои преимущества и недостатки.То, что лучше, будет зависеть от того, что вы собираетесь делать с массивом.В этом отношении первоначальный список может быть для многих целей таким же хорошим.Ни один из них не имеет такую же скорость обработки (для математических операций), как двумерный числовой массив.