Векторизованное решение для генерации матрицы NumPy - PullRequest
1 голос
/ 02 июня 2019

Я ищу какой-нибудь встроенный модуль NumPy или какой-нибудь векторизованный подход, чтобы получить такие матрицы n на n для n>1.Единственное ключевое здесь то, что последний элемент данной строки служит в качестве первого элемента следующей строки.

n = 2
# array([[1, 2], 
#        [2, 3]])

n = 3
# array([[1, 2, 3], 
#        [3, 4, 5], 
#        [5, 6, 7]])

n = 4
# array([[1, 2, 3, 4], 
#        [4, 5, 6, 7], 
#        [7, 8, 9, 10], 
#        [10, 11, 12, 13]])

Моя попытка с использованием списочных представлений.То же самое можно записать в расширенном синтаксисе цикла for.

import numpy as np
n = 4
arr = np.array([[(n-1)*j+i for i in range(1, n+1)] for j in range(n)])
# array([[ 1,  2,  3,  4],
#        [ 4,  5,  6,  7],
#        [ 7,  8,  9, 10],
#        [10, 11, 12, 13]])

Ответы [ 4 ]

3 голосов
/ 02 июня 2019

Если вы хотите, чтобы все было просто (и несколько читабельно), это должно быть сделано:

def ranged_mat(n):
    out = np.arange(1, n ** 2 + 1).reshape(n, n)
    out -= np.arange(n).reshape(n, 1)
    return out

Просто выведите все числа от 1 до n², измените их до желаемой формы блока, затем вычтитеномер строки из каждой строки.

Это то же самое, что и ranged_mat_v2 Дивакара, но мне нравится быть явным с промежуточными формами массива.Не каждый является экспертом в правилах вещания NumPy.

2 голосов
/ 02 июня 2019

Подход № 1

Мы можем использовать np.lib.stride_tricks.as_strided на основе scikit-image's view_as_windows, чтобы получить раздвижные окна. Подробнее об использовании as_strided на основе view_as_windows.

Кроме того, он принимает аргумент step, который идеально подходит для этой проблемы. Следовательно, реализация будет -

from skimage.util.shape import view_as_windows

def ranged_mat(n):
    r  = np.arange(1,n*(n-1)+2)
    return view_as_windows(r,n,step=n-1)

Примеры прогонов -

In [270]: ranged_mat(2)
Out[270]: 
array([[1, 2],
       [2, 3]])

In [271]: ranged_mat(3)
Out[271]: 
array([[1, 2, 3],
       [3, 4, 5],
       [5, 6, 7]])

In [272]: ranged_mat(4)
Out[272]: 
array([[ 1,  2,  3,  4],
       [ 4,  5,  6,  7],
       [ 7,  8,  9, 10],
       [10, 11, 12, 13]])

Подход № 2

Другой с outer-broadcasted-addition -

def ranged_mat_v2(n):
    r = np.arange(n)
    return (n-1)*r[:,None]+r+1

Подход № 3

Мы также можем использовать numexpr модуль , который поддерживает многоядерную обработку и, следовательно, обеспечивает более высокую эффективность при больших n's -

import numexpr as ne

def ranged_mat_v3(n):
    r = np.arange(n)
    r2d = (n-1)*r[:,None]
    return ne.evaluate('r2d+r+1')

Использование нарезки дает нам более эффективное использование памяти -

def ranged_mat_v4(n):
    r  = np.arange(n+1)
    r0 = r[1:]
    r1 = r[:-1,None]*(n-1)
    return ne.evaluate('r0+r1')

Сроки -

In [423]: %timeit ranged_mat(10000)
273 ms ± 3.42 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [424]: %timeit ranged_mat_v2(10000)
316 ms ± 2.03 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [425]: %timeit ranged_mat_v3(10000)
176 ms ± 85.9 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [426]: %timeit ranged_mat_v4(10000)
154 ms ± 82.8 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
1 голос
/ 02 июня 2019

Мы можем использовать NumPy strides для этого:

def as_strides(n):
    m = n**2 - (n-1)
    a = np.arange(1, m+1)
    s = a.strides[0]
    return np.lib.stride_tricks.as_strided(a, shape=(n,n), strides=((n-1)*s,s))

as_strides(2)
rray([[1, 2],
       [2, 3]])

as_strides(3)
array([[1, 2, 3],
       [3, 4, 5],
       [5, 6, 7]])

as_strides(4)
array([[ 1,  2,  3,  4],
       [ 4,  5,  6,  7],
       [ 7,  8,  9, 10],
       [10, 11, 12, 13]])
1 голос
/ 02 июня 2019

Существует также np.fromfunction, как показано ниже. документы здесь

def func(n):
    return np.fromfunction(lambda r,c: (n-1)*r+1+c, shape=(n,n))

Требуется функция, которая вычисляет массив из значений индекса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...