отображение 2d вектора задержки из 1d вектора в numpy - PullRequest
0 голосов
/ 01 июля 2018

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

Я бы хотел, чтобы мой вклад выглядел так:

input:
t = [t1, t2, t3, t4, t5]

out = 
[t5,  0,  0,  0,  0]
[t4, t5,  0,  0,  0]
[t3, t4, t5,  0,  0]
[t2, t3, t4, t5,  0]
[t1, t2, t3, t4, t5]
[ 0, t1, t2, t3, t4]
[ 0,  0, t1, t2, t3]
[ 0,  0,  0, t1, t2]
[ 0,  0,  0,  0, t1]

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

это мой код, использующий цикл for:

import numpy as np

t = np.linspace(-3, 3, 7)
z = np.zeros((2*len(t) - 1, len(t)))

diag = np.arange(len(t))
for index, val in enumerate(np.flip(t, 0)):
    z[diag + index, diag] = val

print(z)

Ответы [ 3 ]

0 голосов
/ 01 июля 2018

То, что вы просите здесь, известно как матрица Теплица , которая:

матрица, в которой каждая нисходящая диагональ слева направо является постоянной

Единственное отличие состоит в том, что вам нужен нижний треугольник вашей матрицы.

Вам повезло, вы можете использовать scipy.linalg.toeplitz для построения вашей матрицы, а затем np.tril для доступа к нижнему треугольнику.

import numpy as np
from scipy.linalg import toeplitz

v = np.array([1, 2, 3, 4, 5])
t = np.pad(v[::-1], (0, 4), mode='constant')

Решите матрицу и получите доступ к нижнему треугольнику:

np.tril(toeplitz(t, v))

И наш вывод!

array([[5, 0, 0, 0, 0],
       [4, 5, 0, 0, 0],
       [3, 4, 5, 0, 0],
       [2, 3, 4, 5, 0],
       [1, 2, 3, 4, 5],
       [0, 1, 2, 3, 4],
       [0, 0, 1, 2, 3],
       [0, 0, 0, 1, 2],
       [0, 0, 0, 0, 1]])

Чтобы обобщить этот метод, просто рассчитайте необходимые отступы для t из формы v:

v = # any one dimension array
t = np.pad(v[::-1], (0, v.shape[0]-1), mode='constant')
0 голосов
/ 01 июля 2018

Вот один векторизованный способ, использующий strides-tricks, который просто использует представление в массив с дополнением нулями и является представлением, эффективно использующим память и, следовательно, производительным -

def map2D(a):
    n = len(a)
    p = np.zeros(n-1,dtype=a.dtype)
    a_ext = np.r_[p,a,p]
    s0 = a_ext.strides[0]
    strided = np.lib.stride_tricks.as_strided
    return strided(a_ext[-n:], (len(a_ext)-n+1,n), (-s0,s0), writeable=False)

Пробный прогон -

In [81]: a = np.array([2,5,6,7,9])

In [82]: map2D(a)
Out[82]: 
array([[9, 0, 0, 0, 0],
       [7, 9, 0, 0, 0],
       [6, 7, 9, 0, 0],
       [5, 6, 7, 9, 0],
       [2, 5, 6, 7, 9],
       [0, 2, 5, 6, 7],
       [0, 0, 2, 5, 6],
       [0, 0, 0, 2, 5],
       [0, 0, 0, 0, 2]])

Если вам нужно, чтобы вывод имел собственное пространство памяти, используйте .copy()

Синхронизация массива элементов 5k -

In [83]: a = np.random.randint(0,9,(5000))

# From this post's soln
In [84]: %timeit map2D(a)
10000 loops, best of 3: 26.3 µs per loop

# If you need output with its own memory space
In [97]: %timeit map2D(a).copy()
10 loops, best of 3: 43.6 ms per loop

# @user3483203's soln
In [87]: %%timeit
    ...: t = np.pad(a[::-1], (0, len(a)-1), mode='constant')
    ...: out = np.tril(toeplitz(t, a))
1 loop, best of 3: 264 ms per loop

# @coldspeed's soln
In [89]: %%timeit
    ...: t = np.pad(a[::-1], (0, len(a)-1), mode='constant')
    ...: out = np.column_stack([np.roll(t, i) for i in range(len(a))])
1 loop, best of 3: 336 ms per loop
0 голосов
/ 01 июля 2018

Не знает о нецикличном методе, но вы, вероятно, могли бы немного ускорить его с roll и column_stack.

v = np.array([1, 2, 3, 4, 5])
t = np.pad(v[::-1], (0, 4), mode='constant')

np.column_stack([np.roll(t, i) for i in range(len(v))]) 
array([[5, 0, 0, 0, 0],
       [4, 5, 0, 0, 0],
       [3, 4, 5, 0, 0],
       [2, 3, 4, 5, 0],
       [1, 2, 3, 4, 5],
       [0, 1, 2, 3, 4],
       [0, 0, 1, 2, 3],
       [0, 0, 0, 1, 2],
       [0, 0, 0, 0, 1]])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...