Есть ли эффективный для памяти способ вставки нулевых столбцов и строк в массив с нулевыми значениями? - PullRequest
2 голосов
/ 23 сентября 2019

У меня есть большая (симметричная) матрица NumPy arr.Это имеет форму arr.shape = (50_000, 50_000).Я хочу вставить несколько нулевых строк / столбцов (симметричным образом).Скажем, количество строк / столбцов, которые я хочу вставить, может быть 123.

Маленький пример

import numpy as np

# Create symmetric square matrix
size = 3
arr = np.array(list(range(size**2))).reshape(size, size)
arr = arr + arr.T

# insert zero columns
# Each "1" represents a column from the original matrix, e.g.
# the first 1 is the first column of arr, the second 1 the second column of arr
# and so on
insert_cols = [1, 0, 0, 1, 0, 1, 0, 0]

# insert the zero rows / columns
current_index = 0
for col in insert_cols:
    if col == 0:
        arr = np.insert(arr, current_index, 0, axis=0)
        arr = np.insert(arr, current_index, 0, axis=1)
    current_index += 1

print(arr)

Если я правильно понимаю np.insert, тоэтот код создает копию массива и постоянно копирует содержимое.

Вопрос

Я подумал, может быть, это может быть проще / эффективнее с одним из классов разреженных матриц ?Есть ли другой способ сделать это более эффективным?

1 Ответ

2 голосов
/ 23 сентября 2019

Учитывая insert_cols, мы можем сделать что-то вроде этого -

n = len(insert_cols)
out = np.zeros((n,n),arr.dtype)
idx = np.flatnonzero(insert_cols)
out[np.ix_(idx,idx)] = arr # or out[idx[:,None],idx] = arr

Либо можно использовать логическую версию для индексации.Следовательно -

insert_cols_bool = np.asarray(insert_cols, dtype=bool)

Затем используйте insert_cols_bool вместо idx.


Разреженная матрица

Чтобы повысить эффективность памяти, мыможно сохранить вывод в виде разреженной матрицы -

from scipy.sparse import coo_matrix

l = len(idx)
r,c = np.broadcast_to(idx[:,None],(l,l)).ravel(),np.broadcast_to(idx,(l,l)).ravel()
out = coo_matrix((arr.ravel(), (r,c)), shape=(n,n))
...