2014-11-15 2 views
1

Когда я делаю массив numpy из своих данных, я получаю (как и ожидалось) список списков, но когда я объявляю типы данных для них, я получаю то, что представляется списком кортежей, что бесполезно. Это проблема, потому что numpy кажется, что первый массив представляет собой 2D-массив, а второй - 1D-массив (он дает .shape как (9,).Я хотел бы иметь возможность поддерживать удобство использования 2D-массива, но давать это типы данных, как показано ниже. есть ли способ сделать это?Как я могу заставить Numpy дать массив списков вместо кортежей?

>>> np.array(mtest) 

array([[',', '7.174707364110744'], 
     ['the', '5.260736372733581'], 
     ['.', '2.630943297842565'], 
     ['of', '2.505952403774265'], 
     ['and', '2.309647686709941'], 
     ['a', '1.7517895552087845'], 
     ['to', '1.7414375486448457'], 
     [';', '1.5612359529022042']], 
     dtype='<U18') 

>>> np.array(mtest, dtype=[('token', np.unicode_, 64),('perc', np.float)]) 

array([(',', 7.174707364110744), ('the', 5.260736372733581), 
     ('.', 2.630943297842565), ('of', 2.505952403774265), 
     ('and', 2.309647686709941), ('a', 1.7517895552087845), 
     ('to', 1.7414375486448457), (';', 1.5612359529022042)], 
     dtype=[('token', '<U64'), ('perc', '<f8')]) 
+1

Что вы здесь такое ['record array'] (http://docs.scipy.org/doc/numpy/reference/generated/numpy.recarray.html), и так оно отображается. Обратите внимание, что первый из них не является списком списков, это массив массивов. –

+1

Я знаю их как * структурированные массивы * (нетривиальный dtype), @AshwiniChaudhary. Массивы записи AFAIK являются подклассом 'ndarrays'. Оба могут иметь тривиальные и нетривиальные типы. Разница для массивов записей - это возможность доступа к полям как членам: 'arr.field1' является 'arr ['field1']' – sebix

ответ

2

Как отметил @Ashwini, это ни списки списков, ни списки кортежей, они оба Numpy массивов. Вы все еще можете получить доступ к «столбцам "(на самом деле называется„поле“, здесь) и„строка“(на самом деле называется„запись“) из этого нового массива. Я не рекомендую преобразовать его в список чего-либо.

a = np.array(mtest, dtype=[('token', np.unicode_, 64),('perc', np.float)]) 

>>> a['token'] 
array([',', 'the', '.', 'of', 'and', 'a', 'to', ';'], 
     dtype='<U64') 

>>> a['perc'] 
array([ 7.17470736, 5.26073637, 2.6309433 , 2.5059524 , 2.30964769, 
     1.75178956, 1.74143755, 1.56123595]) 

>>> a[2] 
('.', 2.630943297842565) 

выше, не является кортежем:

>>> type(a[2]) 
numpy.void 

>>> a[2].dtype 
dtype([('token', '<U64'), ('perc', '<f8')]) 
+0

Проблема заключается в том, что numpy, похоже, не думает, что второй массив (тот, который выглядит как список кортежей) больше представляет собой 2D-массив - он дает свою форму как (9,) и функции, которые нуждаются в 2D-массиве, не могут использовать этот массив. Но первый массив (тот, который выглядит как список списков) работает отлично. Поэтому мне нужен способ сохранить 2D-массив с метками типа данных. Я не был слишком ясен об этом в вопросе, поэтому я его обновлю. – Jono

+0

Это правильно, @Jono, это 1D массив «записей», отсюда и другая терминология «записей» и «полей». Это необходимо, потому что для массива numpy требуется один элемент 'dtype' для _all_, но ваш массив имеет два типа dtypes, поэтому это невозможно. Вам должно быть ясно, почему вам (или этой функции) нужен 2D-массив. – askewchan

+0

А я вижу. Поэтому, если я преобразую float здесь в строки, тогда я смогу работать с ним как 2D-массив. Но я думаю, что аналитические функции, которые я использую, нуждаются в числе чисел, поэтому мне нужно это понять. – Jono

0

Хотя второй массив это не список кортежей (больше чем 1 список списков), его выражение в чистом Питоне. Это не проблема с вашим dtype. Именно так программисты numpy решили построить этот интерфейс.

Для создания 1-й 2d массива я могу начать со списком списков:

x1 = array([[',', '7.174707364110744'], 
     ['the', '5.260736372733581'], 
     ... 
     [';', '1.5612359529022042']], 
     dtype='<U18') 

для создания 2-я, с полями, я должен преобразовать его в список кортежей:

list_of_tuples=[(r[0],float(r[1])) for r in x1] 
x2=np.array(list_of_tuples,dtype=[('token', np.unicode_, 64),('perc', np.float)]) 
x2.tolist() 

производства:

[(u',', 7.174707364110744), 
... 
(u'to', 1.7414375486448457), 
(u';', 1.5612359529022042)] 

Попытка использовать список списков производит 'expected a readable buffer object' ошибку.

Элемент x2 представляет собой массивный массив, форма (). В то время как ряд x1 имеет форму (2,). x2[2] не только показывает, как кортеж, он может быть назначен только кортеж:

x2[2]=(',',1.3) 

Но это не неизменная (как истинный кортеж)

x2[2][0] = ';' 
x2[2]['token'] 

Если бы это был реальный кортеж это задание будет выдавать ошибку, как в:

x2[2].tolist()[0]=':' # TypeError 

Если вам нужен список списков выражения своего 2-го массива, используйте

[list(r) for r in x2.tolist()] 
Смежные вопросы