Самый эффективный способ обратного преобразования массива numpy

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

reversed_arr = arr[::-1]

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

Ответ 1

При создании 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)

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

P.S. Отличное обсуждение видов numpy здесь:

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

Ответ 2

Как упомянуто выше, 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,
)

Ответ 3

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

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

arr1d = np.array(some_sequence)
reversed_arr = np.fliplr([arr1d])[0]

Ответ 4

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

np.flipud(your_array) 

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

С матрицами do

fliplr(matrix)

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

Ответ 5

Я расскажу о более раннем ответе о np.fliplr(). Вот какой код, который демонстрирует построение 1d-массива, преобразование его в массив 2d, перевертывание его, а затем преобразование в 1d-массив. 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]

Ответ 6

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

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

>>> 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])

Но если вы работаете с 2D-массивом...

>>> 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]])

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

>>> for el in np.flip(x).flat:
>>>     print(el, end = ' ')
9 8 7 6 5 4 3 2 1 0

Ответ 7

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

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

Где flipud для 1d arra