#python #numpy
Вопрос:
Можно ли превратить следующий цикл кода Python в код без циклов в Python?
steps = 10000
rho = 0.9
e = np.random.randn(steps)
y = [0]
# Possible to get rid of this loop?
for i in range(len(e)):
y.append(rho*y[i] e[i])
Код предназначен для генерации простых авторегрессионных (порядка 1) временных рядов, где при заданном некотором начальном значении каждое следующее значение соответствует предыдущему времени плюс некоторый случайный шум.
Комментарии:
1. Я не понимаю. В чем конкретно заключается возражение против цикла (чтобы я знал, что приемлемо) ? На что ты надеешься?
2. @MarkSetchell проверьте мой код. @NeverStopLearning пытается создать программу такого типа без цикла, что можно сделать с помощью
iterator
3. @MarkSetchell,
numpy
тег предполагает, что OP хочет быстрогоnumpy
решения, которое использует свои скомпилированные методы всего массива. Для последовательных операций, подобных этой, это может быть сложно.numpy
лучше всего, когда операция применяется ко всему массиву без каких-либо подразумеваемых последовательных действий.4. Изменение
e
наe = e.tolist()
ускорение кода, так как индексирование отдельных элементов списка происходит быстрее.5. @NeverStopLearning, …но что считается «без цикла»? Если вы вызываете функцию, и у этой функции есть цикл, это считается? Если вы используете синтаксис, который неявно зацикливается, это считается? Где именно находится граница того, что является и не является петлей для целей этого вопроса?
Ответ №1:
Проверьте этот код :
import numpy as np
steps = 10000
rho = 0.9
np.random.seed(0)
e = np.random.randn(steps)
z = list(np.zeros(steps))
z[:] = map(lambda x, y: rho*z[y] x, list(e), list(range(steps)))
Способ-2 :
m = list(np.zeros(steps))
m[:] = map(lambda x, y: m.append(rho*m[y] x), list(e), list(range(steps)))
m = m[10000:]
print(m)
Несколько быстрых тестов от ipython
In [1]: timeit z[:] = map(lambda x, y: rho*z[y] x, list(e), list(range(steps)))
1.27 ms ± 19.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [2]: timeit m[:] = map(lambda x, y: m.append(rho*m[y] x), list(e), list(range(steps)))
1.39 ms ± 31.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [3]: timeit for i in range(len(e)): y.append(rho*y[i] e[i])
8.18 ms ± 270 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Комментарии:
1. Ваши
map
тайминги должны включать этуz[:]
часть.map
это просто упрощенный способ выполнения цикла Python. Я не думаю, что это то, о чем просит операция.2. Я не думаю, что это повторяет операцию. Ваш
z
имеет те же ценности,e
что и .