Python 创建一个以元素作为索引函数的numpy矩阵

Python 创建一个以元素作为索引函数的numpy矩阵,python,matrix,numpy,Python,Matrix,Numpy,如何创建一个numpy矩阵,其元素是其索引的函数? 例如,乘法表:a[i,j]=i*j 一个非numpy和非pythonic的方法是创建一个零数组,然后循环通过 毫无疑问,有一种更好的方法可以做到这一点,而不需要循环 但是,最好是直接创建矩阵。这里有一种方法: >>> indices = numpy.indices((5, 5)) >>> a = indices[0] * indices[1] >>> a array([[ 0, 0, 0

如何创建一个numpy矩阵,其元素是其索引的函数? 例如,乘法表:
a[i,j]=i*j

一个非numpy和非pythonic的方法是创建一个零数组,然后循环通过

毫无疑问,有一种更好的方法可以做到这一点,而不需要循环


但是,最好是直接创建矩阵。

这里有一种方法:

>>> 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.index((5,5))
生成两个数组,其中包含5x5数组的x和y索引,如下所示:

>>> 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会将每个位置的两个数组的值相乘,并返回结果。

我现在不使用python,但这一个有效吗

array( [ [ i*j for j in xrange(5)] for i in xrange(5)] )

只是想补充一点,@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

a = (ii[0,...]-1)*ii[1,...]*ii[2,...]
etc

用于乘法

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.frompyfunc
创建
np.ufunc
,然后使用索引创建
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
较大的矩阵:

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

一个通用的解决方案是使用

从文档:

numpy.fromfunction(函数、形状、**kwargs)

通过在每个坐标上执行函数来构造数组。这个 因此,生成的数组在坐标(x,y, z)

下一行应提供所需的矩阵

numpy.fromfunction(lambda i,j:i*j,(5,5))

输出:

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
参数修改坐标数组的形状。

对于a[i,j]=f(i,j)来说,这是可归纳的吗?如果
f
的表达式是矢量化的,它确实是。。。array()强大得令人难以置信!请注意,如果使用此选项,您必须小心不要使用
np.array((i*j表示xrange(4096)中的j)表示xrange(4096)中的i))
,否则会产生意外的结果。吉姆,我很难理解你的联系。我想你是在警告不要把生成器表达式传递给numpy?也涵盖了这一点。这不适用于涉及复杂操作/逻辑的函数。这是因为
numpy
不会为每个坐标调用函数,而是将x和y坐标作为数组传递一次。例如,如果要使用函数:
lambda x,y:2*x if x>y else y/2来构造矩阵。在这种情况下,naive方法是唯一的替代方法吗?@AdityaSriram,您可以将naive方法使用的函数用作可调用函数。但是是的,
fromfunction()
的唯一优点是它将生成索引列表,而不是用户显式地生成它。