Создать пустую матрицу с элементами в зависимости от индексов - PullRequest
5 голосов
/ 06 июня 2011

Как я могу создать пустую матрицу с элементами, являющимися функцией ее индексов? Например, таблица умножения: a[i,j] = i*j

Недопустимым и непифоническим было бы создать массив нулей и затем выполнить цикл.

Нет сомнений в том, что есть лучший способ сделать это без цикла.

Однако, еще лучше было бы создать матрицу сразу.

Ответы [ 5 ]

8 голосов
/ 06 июня 2011

Вот один из способов сделать это:

>>> indices = numpy.indices((5, 5))
>>> a = indices[0] * indices[1]
>>> a
array([[ 0,  0,  0,  0,  0],
       [ 0,  1,  2,  3,  4],
       [ 0,  2,  4,  6,  8],
       [ 0,  3,  6,  9, 12],
       [ 0,  4,  8, 12, 16]])

Для дальнейшего объяснения numpy.indices((5, 5)) генерирует два массива, содержащих индексы x и y массива 5x5, например:

>>> numpy.indices((5, 5))
array([[[0, 0, 0, 0, 0],
        [1, 1, 1, 1, 1],
        [2, 2, 2, 2, 2],
        [3, 3, 3, 3, 3],
        [4, 4, 4, 4, 4]],

       [[0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4],
        [0, 1, 2, 3, 4]]])

Когда вы умножаете эти два массива, numpy умножает значение двух массивов в каждой позиции и возвращает результат.

4 голосов
/ 07 ноября 2014

Для умножения

np.multiply.outer(np.arange(5), np.arange(5))  # a_ij = i * j

и вообще

np.frompyfunc(
    lambda i, j: f(i, j), 2, 1
).outer(
    np.arange(5),
    np.arange(5),
).astype(np.float64)  # a_ij = f(i, j)

в основном вы создаете np.ufunc через np.frompyfunc, а затем outer с индексами.

Редактировать

Сравнение скорости между различными решениями.

Маленькие матрицы:

Eyy![1]: %timeit np.multiply.outer(np.arange(5), np.arange(5))
100000 loops, best of 3: 4.97 µs per loop

Eyy![2]: %timeit np.array( [ [ i*j for j in xrange(5)] for i in xrange(5)] )
100000 loops, best of 3: 5.51 µs per loop

Eyy![3]: %timeit indices = np.indices((5, 5)); indices[0] * indices[1]
100000 loops, best of 3: 16.1 µs per loop

Большие матрицы:

Eyy![4]: %timeit np.multiply.outer(np.arange(4096), np.arange(4096))
10 loops, best of 3: 62.4 ms per loop

Eyy![5]: %timeit indices = np.indices((4096, 4096)); indices[0] * indices[1]
10 loops, best of 3: 165 ms per loop

Eyy![6]: %timeit np.array( [ [ i*j for j in xrange(4096)] for i in xrange(4096)] )
1 loops, best of 3: 1.39 s per loop
3 голосов
/ 12 июля 2018

Общее решение будет использовать np.fromfunction ()

Из документа:

numpy.fromfunction(function, shape, **kwargs)

Constructмассив путем выполнения функции над каждой координатой.Таким образом, результирующий массив имеет значение fn (x, y, z) в точке с координатами (x, y, z).

В приведенной ниже строке должна быть указана необходимая матрица.1016 *

Вывод:

array([[  0.,   0.,   0.,   0.,   0.],
       [  0.,   1.,   2.,   3.,   4.],
       [  0.,   2.,   4.,   6.,   8.],
       [  0.,   3.,   6.,   9.,  12.],
       [  0.,   4.,   8.,  12.,  16.]])

Первый параметр функции - это вызываемый объект, который выполняется для каждой из координат.Если foo - это функция, которую вы передаете в качестве первого аргумента, foo(i,j) будет значением в (i,j).Это относится и к более высоким измерениям.Форма массива координат может быть изменена с помощью параметра shape.

3 голосов
/ 06 июня 2011

В данный момент я далеко от своего питона, но работает ли этот?

array( [ [ i*j for j in xrange(5)] for i in xrange(5)] )
2 голосов
/ 06 июня 2011

Просто хотел добавить, что ответ @ Senderle можно обобщить для любой функции и измерения:

dims = (3,3,3) #i,j,k
ii = np.indices(dims)

Затем можно вычислить a[i,j,k] = i*j*k как

a = np.prod(ii,axis=0)

или a[i,j,k] = (i-1)*j*k

1010

и т. Д.

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