#python #numpy #array-broadcasting
Вопрос:
Я хочу построить массив точек, где каждая строка зависит от соответствующей строки массива временных шагов, как в:
steps = 5
output = np.empty((steps, 3))
timesteps = np.linspace(0, 1, steps)
for i, step in enumerate(timesteps):
output[i] = [sin(step), cos(step), 0]
С ожидаемым результатом:
[[0. 1. 0. ]
[0.24740396 0.96891242 0. ]
[0.47942554 0.87758256 0. ]
[0.68163876 0.73168887 0. ]
[0.84147098 0.54030231 0. ]]
Как я могу векторизовать эту операцию?
Я мог бы назначить каждый столбец независимо, вот так:
out[:, 0] = np.sin(timesteps)
out[:, 1] = np.cos(timesteps)
out[:, 2] = 0
Но я хотел бы сохранить подход, основанный на строках, для удобства чтения, если это возможно.
Я думал о чем-то вроде
output[:] = [np.sin(timesteps[:]), np.cos(timestep[:]), 0]
но очевидно, что это не работает из-за установки элемента массива с последовательностью.
Комментарии:
1. Назначение столбцов — правильный способ сделать это. Я не понимаю, как это делает вещи менее читабельными.
2. @TimRoberts Я полагаю, что это немного скрывает отношение точка=строка, но да, это не большая проблема.
Ответ №1:
вы можете создать массив numpy следующим образом:
np.array([np.sin(timesteps), np.cos(timesteps), [0]*len(timesteps)])
Однако это устанавливает синусы в качестве первой линии, косинусы в качестве второй и так далее. Чтобы изменить их с строк на столбцы, вы можете использовать transpose()
метод, также доступный через .T
атрибут. Наконец-то ты получишь:
output = np.array([np.sin(timesteps),
np.cos(timesteps),
[0]*len(timesteps)]).transpose()
или
output = np.array([np.sin(timesteps), np.cos(timesteps), [0]*len(timesteps)]).T
Я нахожу это достаточно близким к тому, что вы пробовали, и думаю, что это нормально в отношении проблемы «читабельности». Чтобы убедиться, что это действительно то, что вы хотите:
import numpy as np
steps = 5
output = np.empty((steps, 3))
timesteps = np.linspace(0, 1, steps)
for i, step in enumerate(timesteps):
output[i] = [np.sin(step), np.cos(step), 0]
output -= np.array([np.sin(timesteps), np.cos(timesteps), [0]*len(timesteps)]).transpose()
print(output)
> [[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]
ПРИМЕЧАНИЕ: [0]*len(timesteps)
создайте список размеров len(timesteps)
, заполненный только нулями
Ответ №2:
У меня есть что-то похожее на это, можешь попробовать ?
output[:] = [np.sin(timesteps[:]), np.cos(timestep[:]), 0]
Вот мое решение:
import numpy as np
steps = 5
timesteps = np.linspace(0, 1, steps)
out=np.concatenate(([np.sin(timesteps)],[np.cos(timesteps)],[np.zeros(steps)]))
out=out.transpose()
out
array([[0. , 1. , 0. ],
[0.24740396, 0.96891242, 0. ],
[0.47942554, 0.87758256, 0. ],
[0.68163876, 0.73168887, 0. ],
[0.84147098, 0.54030231, 0. ]])
Я думаю, что это было бы полезно, дайте мне знать, если какая-либо проблема сохранится.