【问题标题】:Is there a memory-efficient way of inserting zero-columns and rows into a numpy array?是否有一种将零列和行插入 numpy 数组的内存有效方法?
【发布时间】:2019-09-23 09:06:25
【问题描述】:

我有一个大的(对称的)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 的理解正确,那么这段代码会创建数组的副本并一直复制内容。

问题

我认为使用sparse matrix classes 之一可能会更简单/更有效?还有其他方法可以提高效率吗?

【问题讨论】:

  • 是否可以选择以某个固定大小预分配整个数组?
  • 我已经有一个类似的案例,我花了几个小时来解决这个问题:根据我的理解(这是非常基本的,我将遵循这篇文章),没有办法使用 np.insert 进行有效插入。插入或 np.concatenate。我发现最好的方法是将数组转换为列表,然后插入您需要的内容,然后将列表重新转换为数组。
  • @MateenUlhaq 是的!预分配肯定是可能的
  • 显然结果必须是一个新数组(resize 方法的功能非常有限),因此您必须复制源的所有值。我不会迭代insert;新数组太多。

标签: python python-3.x numpy python-3.6


【解决方案1】:

鉴于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))

【讨论】:

  • 这看起来好多了 - 这已经很酷了(+1)。但是,我不确定out[np.ix_(idx, idx)] = arr 的开销。它基本上只在阵列上运行一次吗?
  • @MartinThoma Well np.ix_(idx, idx) 创建一个 2D 开放网格,然后索引到 out 数组,并一步将 arr 值分配给它。
猜你喜欢
  • 2022-06-10
  • 1970-01-01
  • 2020-01-14
  • 2020-11-03
  • 1970-01-01
  • 2012-01-18
  • 2014-10-08
  • 1970-01-01
  • 2015-03-12
相关资源
最近更新 更多