Python - 在我的函数中写一个就地选项 [如何防止覆盖我的输入向量]

Python - writing an in-place option in my function [how to prevent overwriting my input vector]

我正在编写一个函数,从稀疏向量中提取最高的 x 值(如果少于 x,则更少的值)。我想像许多函数一样包含一个“就地”选项,如果选项为真,它会删除最高值,如果选项为假,则保留它们。

我的问题是我当前的函数正在覆盖输入向量,而不是保持原样。我不确定为什么会这样。我希望解决我的设计问题的方法是包含一个 if 语句,该语句将使用 copy.copy() 复制输入,但这会引发值错误(ValueError:行索引超出矩阵维度),这没有意义对我来说。

代码:

from scipy.sparse import csr_matrix
import copy

max_loc=20
data=[1,3,3,2,5]
rows=[0]*len(data)
indices=[4,2,8,12,7]

sparse_test=csr_matrix((data, (rows,indices)), shape=(1,max_loc))

print(sparse_test)

def top_x_in_sparse(in_vect,top_x,inplace=False):
    if inplace==True:
        rvect=in_vect
    else:
        rvect=copy.copy(in_vect)
    newmax=top_x
    count=0
    out_list=[]
    while newmax>0:
        newmax=1
        if count<top_x:
            out_list+=[csr_matrix.max(rvect)]
            remove=csr_matrix.argmax(rvect)
            rvect[0,remove]=0
            rvect.eliminate_zeros()
            newmax=csr_matrix.max(rvect)
            count+=1
        else:
            newmax=0
    return out_list

a=top_x_in_sparse(sparse_test,3)

print(a)

print(sparse_test)

我的问题分为两部分:

  1. 如何防止此函数覆盖向量?
  2. 如何添加就地选项?

您真的只是不想循环播放。使用 .eliminate_zeros() 在每个循环迭代中重新分配这些数组是最慢的事情,但不是不这样做的唯一原因。

import numpy as np
from scipy.sparse import csr_matrix

max_loc=20
data=[1,3,3,2,5]
rows=[0]*len(data)
indices=[4,2,8,12,7]

sparse_test=csr_matrix((data, (rows,indices)), shape=(1,max_loc))

像这样会更好:

def top_x_in_sparse(in_vect,top_x,inplace=False):
    
    n = len(in_vect.data)
    
    if top_x >= n:
        if inplace:
            out_data = in_vect.data.tolist()
            in_vect.data = np.array([], dtype=in_vect.data.dtype)
            in_vect.indices = np.array([], dtype=in_vect.indices.dtype)
            in_vect.indptr = np.array([0, 0], dtype=in_vect.indptr.dtype)
            return out_data
        else:
            return in_vect.data.tolist()
        
    else:
        k = n - top_x
        partition_idx = np.argpartition(in_vect.data, k)

        if inplace:
            out_data = in_vect.data[partition_idx[k:n]].tolist()
            in_vect.data = in_vect.data[partition_idx[0:k]]
            in_vect.indices = in_vect.indices[partition_idx[0:k]]
            in_vect.indptr = np.array([0, len(in_vect.data)], dtype=in_vect.indptr.dtype)            
            return out_data
        else:
            return in_vect.data[partition_idx[k:n]].tolist()
    

如果您需要对返回值进行排序,您当然也可以这样做。

a=top_x_in_sparse(sparse_test,3,inplace=False)

>>> print(a)
[3, 5, 3]

>>> print(sparse_test)
  (0, 2)    3
  (0, 4)    1
  (0, 7)    5
  (0, 8)    3
  (0, 12)   2

b=top_x_in_sparse(sparse_test,3,inplace=True)

>>> print(b)
[3, 5, 3]

>>> print(sparse_test)
  (0, 4)    1
  (0, 12)   2

另外根据评论中的问题:稀疏数组对象的浅表副本不会复制保存数据的 numpy 数组。稀疏对象仅具有对这些对象的引用。深拷贝会得到它们,但是使用内置的拷贝方法已经知道哪些被引用的东西需要被复制,哪些不需要。