2014-01-26 5 views
6

Я хотел бы иметь возможность использовать синтаксис понимания списка для работы с массивами NumPy.Синтаксис сравнения NumPy List

Например, я хотел бы что-то вроде ниже явно неправильного кода, чтобы просто воспроизвести тот же массив.

>>> X = np.random.randn(8,4) 
>>> [[X[i,j] for i in X] for j in X[i]] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
IndexError: arrays used as indices must be of integer (or boolean) type 

Что такое простой способ сделать это, чтобы избежать использования range(len(X)?

+1

X [I, J] является синтаксически X [I] [J] в NumPy –

+9

Не делайте этого! Это поражает всю цель использования NumPy. – user2357112

+0

И (даже если вы его исправите), это не приведет к воспроизведению массива, вместо этого будет создан список списков. – abarnert

ответ

0

Возможно, вы употребите следующее:

>>> [[X[i,j] for j in range(X.shape[1])] for i in range(X.shape[0])] 
[[0.62757350000000001, -0.64486080999999995, -0.18372566000000001, 0.78470704000000002], 
[1.78209799, -1.336448459999999 9, -1.3851422200000001, -0.49668994], 
[-0.84148266000000005, 0.18864597999999999, -1.1135151299999999, -0.40225053999999 999], 
[0.93852824999999995, 0.24652238000000001, 1.1481637499999999, -0.70346624999999996], 
[0.83842508000000004, 1.0058 697599999999, -0.91267403000000002, 0.97991269000000003], 
[-1.4265273000000001, -0.73465904999999998, 0.6684284999999999 8, -0.21551155], 
[-1.1115614599999999, -1.0035033200000001, -0.11558254, -0.4339924], 
[1.8771354, -1.0189299199999999, - 0.84754008000000003, -0.35387946999999997]] 

numpy.ndarray.copy Использование:

>>> X.copy() 
array([[ 0.6275735 , -0.64486081, -0.18372566, 0.78470704], 
     [ 1.78209799, -1.33644846, -1.38514222, -0.49668994], 
     [-0.84148266, 0.18864598, -1.11351513, -0.40225054], 
     [ 0.93852825, 0.24652238, 1.14816375, -0.70346625], 
     [ 0.83842508, 1.00586976, -0.91267403, 0.97991269], 
     [-1.4265273 , -0.73465905, 0.6684285 , -0.21551155], 
     [-1.11156146, -1.00350332, -0.11558254, -0.4339924 ], 
     [ 1.8771354 , -1.01892992, -0.84754008, -0.35387947]]) 
+0

Он говорит, что пытается создать ту же самую форму, с которой он начал, так что это даже не «транспонировать», это просто «копировать». – abarnert

+0

@abarnert, Спасибо за комментарий. Я обновил ответ. – falsetru

17

Во-первых, вы не должны использовать Numpy массивы как списки списков.

Во-вторых, давайте забудем о NumPy; ваш listcomp не имеет никакого смысла в первую очередь, даже для списков списков.

Во внутреннем понимании, for i in X будет перебирать строки в X. Эти строки не являются числами, они перечислены (или, в NumPy, 1D массивов), так X[i] не имеет никакого смысла. Возможно, вам понадобилось i[j].

По внешнему пониманию, for j in X[i] имеет ту же проблему, но имеет еще большую проблему: нет значения i. У вас есть понимание зацикливания над каждым iвнутри это понимание.

Если вы смущены постижению, записать его в качестве явного for заявления, как описано в разделе учебника по List Comprehensions:

tmp = [] 
for j in X[i]: 
    tmp.append([X[i,j] for i in X]) 

... который расширяется:

tmp = [] 
for j in X[i]: 
    tmp2 = [] 
    for i in X: 
     tmp2.append(X[i,j]) 
    tmp.append(tmp2) 

... что должно сделать очевидным, что здесь не так.


Я думаю, что ты хотел:

[[cell for cell in row] for row in X] 

Снова включите его в явные for заявления:

tmp = [] 
for row in X; 
    tmp2 = [] 
    for cell in row: 
     tmp2.append(cell) 
    tmp.append(tmp2) 

Очевидно, что это правильно.

Или, если вы действительно хотите использовать индексацию (но не):

[[X[i][j] for j in range(len(X[i]))] for i in range(len(X))] 

Итак, вернемся к NumPy.С точкой зрения NumPy, что последняя версия:

[[X[i,j] for j in range(X.shape[1])] for i in range(x.shape[0])] 

... и если вы хотите идти в столбцах порядка вместо строки-майор, вы можете (в отличие от списка списков):

[[X[i,j] for i in range(X.shape[0])] for j in range(x.shape[1])] 

... но это, конечно же, перенесет массив, который вы не хотите делать.

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


Конечно путь право сделать копию массива использовать copy метод:

X.copy() 

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

X.T 
6

Легкий способ не делать этого. Вместо этого используйте неявную векторию numpy. Например, если у вас есть массивы A и B следующим образом:

A = numpy.array([[1, 3, 5], 
       [2, 4, 6], 
       [9, 8, 7]]) 
B = numpy.array([[5, 3, 5], 
       [3, 5, 3], 
       [5, 3, 5]]) 

затем следующий код с помощью списковых:

C = numpy.array([[A[i, j] * B[i, j] for j in xrange(A.shape[1])] 
       for i in xrange(A.shape[0])]) 

может быть гораздо легче записать как

C = A * B 

It также будет работать намного быстрее. Как правило, вы будете генерировать более быстрый и понятный код, если вы не используете методы списка с numpy, чем если бы вы это делали.

Если вы действительно хотите использовать списки, то применяются стандартные методы написания списка Python. Перебирать элементы, а не индексы:

C = numpy.array([[a*b for a, b in zip(a_row, b_row)] 
       for a_row, b_row in zip(A, B)] 

Таким образом, ваш пример кода станет

numpy.array([[elem for elem in x_row] for x_row in X]) 
+0

Примечание: для эффективности, если вы больше не будете использовать список, вы можете использовать 'np.asarray()' вместо 'np.array()'. Это же функция с 'copy = False'. –

+0

@RicardoCruz: Он собирается копировать в любом случае. 'asarray' может только избежать копирования, если вход уже является массивом. – user2357112

+0

@ user237112, О, спасибо, что указали это. Я этого не знал. –

1

Другим вариантом (хотя и не обязательно производительными) является переосмысление вашей проблемы как карта вместо понимания и написать ufunc:

http://docs.scipy.org/doc/numpy/reference/ufuncs.html

можно назвать функционально-облегчённые процедуры, как:

http://docs.scipy.org/doc/numpy/reference/generated/numpy.apply_over_axes.html http://docs.scipy.org/doc/numpy/reference/generated/numpy.vectorize.html

Etc.

Смежные вопросы