Как назначить строки массива np в соответствии со строками другого массива?

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

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