Самый эффективный способ обратить вспять массив - PullRequest
240 голосов
/ 21 июля 2011

Верьте или нет, после профилирования моего текущего кода, повторяющаяся операция реверсии numpy массива съела гигантский кусок времени выполнения.Сейчас у меня есть общий метод, основанный на представлении:

reversed_arr = arr[::-1]

Есть ли какой-нибудь другой способ сделать это более эффективно, или это всего лишь иллюзия из-за моей одержимости нереалистичной работой с клочьями?

Ответы [ 7 ]

204 голосов
/ 21 июля 2011

Когда вы создаете reversed_arr, вы создаете представление в исходном массиве.Затем вы можете изменить исходный массив, и представление обновится, чтобы отразить изменения.

Вы воссоздаете представление чаще, чем вам нужно?Вы должны быть в состоянии сделать что-то вроде этого:

arr = np.array(some_sequence)
reversed_arr = arr[::-1]

do_something(arr)
look_at(reversed_arr)
do_something_else(arr)
look_at(reversed_arr)

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

PS Отличное обсуждение numpy представлений здесь:

Просмотр массива numpy?

43 голосов
/ 05 июля 2017

Как упомянуто выше, a[::-1] на самом деле только создает представление, поэтому это операция с постоянным временем (и, как таковая, не занимает больше времени по мере роста массива). Если вам нужно, чтобы массив был смежным (например, потому что вы выполняете с ним много векторных операций), ascontiguousarray примерно так же быстро, как flipup / fliplr:

enter image description here


Код для генерации сюжета:

import numpy
import perfplot


perfplot.show(
    setup=lambda n: numpy.random.randint(0, 1000, n),
    kernels=[
        lambda a: a[::-1],
        lambda a: numpy.ascontiguousarray(a[::-1]),
        lambda a: numpy.fliplr([a])[0]
        ],
    labels=['a[::-1]', 'ascontiguousarray(a[::-1])', 'fliplr'],
    n_range=[2**k for k in range(25)],
    xlabel='len(a)',
    logx=True,
    logy=True,
    )
37 голосов
/ 18 июля 2014

np.fliplr() переворачивает массив слева направо.

Обратите внимание, что для 1d-массивов вам нужно немного его обмануть:

arr1d = np.array(some_sequence)
reversed_arr = np.fliplr([arr1d])[0]
36 голосов
/ 05 июня 2016

Поскольку это, кажется, еще не отмечено как ответ ... Ответ Томаса Арилдсена должен быть правильным: просто используйте

np.flipud(your_array) 

, если это массив 1d (массив столбцов).

С матрицами:

fliplr(matrix)

, если вы хотите перевернуть строки, и flipud(matrix), если вы хотите перевернуть столбцы.Нет необходимости превращать массив из 1d-столбца в двухмерный массив строк (матрица с одним None-слоем), а затем переворачивать его.

3 голосов
/ 30 июня 2015

Я более подробно остановлюсь на предыдущем ответе о np.fliplr(). Вот некоторый код, который демонстрирует построение 1d-массива, преобразование его в 2-мерный массив, его переворачивание, а затем преобразование обратно в 1-мерный массив. time.clock() будет использоваться для хранения времени, которое представлено в секундах.

import time
import numpy as np

start = time.clock()
x = np.array(range(3))
#transform to 2d
x = np.atleast_2d(x)
#flip array
x = np.fliplr(x)
#take first (and only) element
x = x[0]
#print x
end = time.clock()
print end-start

С заявлением на печать без комментариев:

[2 1 0]
0.00203907123594

С комментариями к печати:

5.59799927506e-05

Итак, с точки зрения эффективности, я думаю, что это прилично. Для тех из вас, кто любит делать это в одной строке, вот эта форма.

np.fliplr(np.atleast_2d(np.array(range(3))))[0]
0 голосов
/ 17 января 2019

В продолжение того, что сказали другие, я приведу короткий пример.

Если у вас есть одномерный массив ...

>>> import numpy as np
>>> x = np.arange(4) # array([0, 1, 2, 3])
>>> x[::-1] # returns a view
Out[1]: 
array([3, 2, 1, 0])

Но если вы работаете с двумерным массивом...

>>> x = np.arange(10).reshape(2, 5)
>>> x
Out[2]:
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])

>>> x[::-1] # returns a view:
Out[3]: array([[5, 6, 7, 8, 9],
               [0, 1, 2, 3, 4]])

Это на самом деле не переворачивает Матрицу.

Следует использовать np.flip для фактического переворота элементов

>>> np.flip(x)
Out[4]: array([[9, 8, 7, 6, 5],
               [4, 3, 2, 1, 0]])

Если вы хотите напечататьэлементы матрицы одно за другим используют квартиру вместе с flip

>>> for el in np.flip(x).flat:
>>>     print(el, end = ' ')
9 8 7 6 5 4 3 2 1 0
0 голосов
/ 19 апреля 2017

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

b = numpy.flipud(numpy.array(a.split(),float))

Где flipud для 1d arra

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