如何有效地展开矩阵的值与小块?

共3个回答,已解决, 标签: 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

这将产生:

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)

是否有更快的方法, 或在单个不稳定的操作中执行此操作的方法?

第1个答案(采用)

广播的比较是你的朋友:

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

 np.array_equal(A, B)
# True

其想法是以这样一种方式扩大尺寸, 使比较能够以所需的方式播出。


正如 @Alex 莱利在评论中指出的, 你可以用 np.equal.outer 它来避免自己做索引的事情,

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

np.array_equal(A, B)
# True
第2个答案

您可以在这里使用一些广播:

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

替代方法 indices :

X, Y = np.indices(M.shape)
Z = np.equal(M, X[:, None]).astype(int)
第3个答案

您可以像这样索引到标识矩阵中

 A = np.identity(N, int)[:, M]

左右这样

 A = np.identity(N, int)[M.T].T

或使用新的 (v1.15.0)put_along_axis

A = np.zeros((N,5,5), int)
np.put_along_axis(A, M[None], 1, 0)

请注意, 如果 N 大于 5, 则创建 NxN 标识矩阵可能被视为浪费。我们可以使用步幅技巧来缓解这种情况:

def read_only_identity(N, dtype=float):
    z = np.zeros(2*N-1, dtype)
    s, = z.strides
    z[N-1] = 1
    return np.lib.stride_tricks.as_strided(z[N-1:], (N, N), (-s, s))

相关问题

通过随机抽样其他列数据创建新列 如何使用熊猫获得包括每一个组合的计数 如何有效地展开矩阵的值与小块? "注意: 未定义的变量"、"注意: 未定义的索引" 和 "注意: 未定义的偏移量" 使用 PHP 删除数字数组中的所有重复数字 [重复] 使用数组中的键获取最小值 将一个六位数的数字列拆分为分隔的列,保留一位数的 [] Numpy 1D 数组: 重复超过 n 次的屏蔽元素 在 numpy [复制] 中快速找到对称对