Диагональная укладка в NumPy? - PullRequest
4 голосов
/ 23 августа 2011

Таким образом, numpy имеет несколько удобных функций для объединения нескольких массивов в один, например, hstack и vstack. Мне интересно, есть ли что-нибудь подобное, кроме как для размещения массивов компонентов по диагонали?

Скажем, у меня есть N массивов формы (n_i, m_i), и я хочу объединить их в один массив размера (sum_ {1, N} n_i, sum_ {1, N} m_i), так что массивы компонентов формировать блоки по диагонали массива результатов.

И да, я знаю, как решить это вручную, например. с подходом, описанным в Как «встроить» небольшой массив с нуля в предопределенный блок большого массива с нулями? . Просто интересно, есть ли более простой способ.

Ах, Как я могу преобразовать блоки в блок-диагональную матрицу (NumPy) упоминает, что scipy.linalg.block_diag () является решением, за исключением того, что версия scipy, установленная на моей рабочей станции, настолько старая, что не имеет его Есть еще идеи?

1 Ответ

7 голосов
/ 23 августа 2011

Кажется, block_diag делает именно то, что вы хотите. Так что если по какой-то причине вы не можете обновить scipy, то вот источник v0.8.0, если вы хотите просто определить его!

def block_diag(*arrs):
    """Create a block diagonal matrix from the provided arrays.

    Given the inputs `A`, `B` and `C`, the output will have these
    arrays arranged on the diagonal::

        [[A, 0, 0],
         [0, B, 0],
         [0, 0, C]]

    If all the input arrays are square, the output is known as a
    block diagonal matrix.

    Parameters
    ----------
    A, B, C, ... : array-like, up to 2D
        Input arrays.  A 1D array or array-like sequence with length n is
        treated as a 2D array with shape (1,n).

    Returns
    -------
    D : ndarray
        Array with `A`, `B`, `C`, ... on the diagonal.  `D` has the
        same dtype as `A`.

    References
    ----------
    .. [1] Wikipedia, "Block matrix",
           http://en.wikipedia.org/wiki/Block_diagonal_matrix

    Examples
    --------
    >>> A = [[1, 0],
    ...      [0, 1]]
    >>> B = [[3, 4, 5],
    ...      [6, 7, 8]]
    >>> C = [[7]]
    >>> print(block_diag(A, B, C))
    [[1 0 0 0 0 0]
     [0 1 0 0 0 0]
     [0 0 3 4 5 0]
     [0 0 6 7 8 0]
     [0 0 0 0 0 7]]
    >>> block_diag(1.0, [2, 3], [[4, 5], [6, 7]])
    array([[ 1.,  0.,  0.,  0.,  0.],
           [ 0.,  2.,  3.,  0.,  0.],
           [ 0.,  0.,  0.,  4.,  5.],
           [ 0.,  0.,  0.,  6.,  7.]])

    """
    if arrs == ():
        arrs = ([],)
    arrs = [np.atleast_2d(a) for a in arrs]

    bad_args = [k for k in range(len(arrs)) if arrs[k].ndim > 2]
    if bad_args:
        raise ValueError("arguments in the following positions have dimension "
                            "greater than 2: %s" % bad_args) 

    shapes = np.array([a.shape for a in arrs])
    out = np.zeros(np.sum(shapes, axis=0), dtype=arrs[0].dtype)

    r, c = 0, 0
    for i, (rr, cc) in enumerate(shapes):
        out[r:r + rr, c:c + cc] = arrs[i]
        r += rr
        c += cc
    return out
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...