如何使用numpy有效地按值展开矩阵?

sev*_*bar 7 python arrays numpy

我有一个矩阵,M其中的值为0 N。我想展开此矩阵以创建一个新的矩阵A,其中每个子矩阵都A[i, :, :]表示M == i。

下面的解决方案使用一个循环。

# Example Setup
import numpy as np

np.random.seed(0)
N = 5
M = np.random.randint(0, N, size=(5,5))

# Solution with Loop
A = np.zeros((N, M.shape[0], M.shape[1]))
for i in range(N):
    A[i, :, :] = M == i
Run Code Online (Sandbox Code Playgroud)

这样产生:

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

M.shape
# (5, 5)


A 
array([[[0, 1, 0, 0, 0],
        [0, 0, 0, 0, 1],
        [1, 0, 0, 0, 1],
        [0, 0, 1, 0, 0],
        [0, 1, 0, 1, 0]],
       ...
       [[1, 0, 0, 0, 0],
        [0, 0, 0, 1, 0],
        [0, 1, 0, 0, 0],
        [0, 0, 0, 0, 1],
        [0, 0, 0, 0, 0]]])

A.shape
# (5, 5, 5)
Run Code Online (Sandbox Code Playgroud)

有没有更快的方法,还是可以在单个numpy操作中做到这一点?

cs9*_*s95 6

广播比较是您的朋友:

B = (M[None, :] == np.arange(N)[:, None, None]).view(np.int8)

 np.array_equal(A, B)
# True
Run Code Online (Sandbox Code Playgroud)

想法是扩大尺寸,以便可以以期望的方式广播比较。


正如@Alex Riley在评论中所指出的那样,您np.equal.outer可以避免自己做索引工作,

B = np.equal.outer(np.arange(N), M).view(np.int8)

np.array_equal(A, B)
# True
Run Code Online (Sandbox Code Playgroud)


use*_*203 6

您可以在此处使用一些广播:

P = np.arange(N)
Y = np.broadcast_to(P[:, None], M.shape)
T = np.equal(M, Y[:, None]).astype(int)
Run Code Online (Sandbox Code Playgroud)

替代使用indices

X, Y = np.indices(M.shape)
Z = np.equal(M, X[:, None]).astype(int)
Run Code Online (Sandbox Code Playgroud)