0

我的目标和问题的描述:

我目前正在使用 python(版本 3.6.12)中的scanpyannadata包。如果你不熟悉这些包,只知道在属性中anndata.AnnData存储了一个数据矩阵(numpy.ndarrayX。的列在属性中X描述,行在属性中描述。有关更多信息,请参阅此链接panda.DataFramevarobs

我的目标是拥有一个从该类继承的类(例如 A 类)anndata.AnnData。在这个子类中,我想实现一些处理方法来过滤掉某些行或列。更重要的是,我还希望这些方法以“就地”方式修改属性,而不需要返回副本(即没有return self)。但是,当我删除return self方法中的 时,不会修改类的实例。更准确地说,在self函数内部修改了,但类的实例保持不变。

代码示例:

想象以下示例,其中 A 类继承自anndata.AnnData. 类 A 有一个称为remove_last_row()删除类 A 实例的最后一行(即 obs)的方法。

import anndata
import numpy as np

class A(anndata.AnnData): 
    
    def __init__(self, adata, data_type=None): 
        """
        Initition method 
        
        Parameters: 
        -----------
        adata: anndata.AnnData, 
            The Anndata object
        """
        super().__init__(adata)
        
    def remove_last_row(self): 
        """
        Remove the last row of the anndata object
        """
        
        print("--> In A.remove_last_row() method:")
        print("before filtering: number rows = ", self.X.shape[0])
        
        # get the row index to keep (i.e. the index of the obs without the last one)
        index_to_keep = self.obs[:-1].values.astype(int)
        # Keep only those index: 
        self = self[index_to_keep, :]
        
        print("after filtering: number rows = ", self.X.shape[0])
        print("<-- exit A.remove_last_row() method.")

使用该remove_last_row()方法时的问题是实例(self)的行在函数内部被删除但它没有修改类的实例。请参见下面的示例:

# Create an AnnData object: 
adata = anndata.AnnData(np.array([[0, 0, 0], [1, 1, 1], [2, 2, 2]]))
    
# Create object A that is inherited from AnnData
obj_A = A(adata = adata)
    
# Test remove_last_row method
obj_A.remove_last_row()

print()
print("obj_A.X attribute = \n", obj_A.X)

结果是:

--> 在 A.remove_last_row() 方法中:
过滤前:number rows = 3
过滤后:number rows = 2
<-- 退出 A.remove_last_row() 方法。

obj_A.X 属性 =
[[0. 0. 0.]
[1. 1. 1.]
[2. 2. 2.]]

我们看到在remove_last_row()方法中,最后一行self在函数内部被删除。但是,obj_A(A 类的实例)没有被此方法修改。如何在不添加return self.


附加信息:

  • Python版本=3.6.12
  • numpy 版本=1.19.1
  • 数据版本=0.7.4
  • 扫描版本=1.6.0

我还测试了一个我调用的方法,addition()它为数组的每个元素添加了一个特定的值X。使用这种方法,我不会遇到这个问题。

如果方法addition()在 A 类中:

   def addition(self, x=1): 
        """
        Add a value of x for each element in the X numpy array in the AnnData object
        
        Parameters: 
        -----------
        x: float,
            The value added to every element 
        """
        self.X += x

我们可以测试:

# Create an AnnData object: 
adata = anndata.AnnData(np.array([[0, 0, 0], [1, 1, 1], [2, 2, 2]]))

# Create object A that is inherited from AnnData
print("Before addition")
obj_A = A(adata = adata)
print("obj_A.X attribute = \n", obj_A.X)

# Test the addition method
print()
obj_A.addition(x=1)
print()
print("After addition")
print("obj_A.X attribute = \n", obj_A.X)

结果是:

添加之前
obj_A.X 属性 =
[[0. 0. 0.]
[1. 1. 1.]
[2. 2. 2.]]

添加
obj_A.X 属性后 =
[[1. 1. 1.]
[2. 2. 2.]
[3. 3. 3.]]

如您所见,该addition()方法有效。它能够修改类的实例。

4

0 回答 0