scanpy 單細胞分析包圖文詳解 01 | 深入理解 AnnData 數據結構


一、環境准備:

搭建 Python 高效開發環境: Pycharm + Anaconda

二、安裝 scanpy

pip install scanpy

三、AnnData

1、AnnData 介紹與結構

AnnData 是用於存儲數據的對象,一般作為 scanpy 的數據存儲格式。

image.png

主要由以下幾部分構成:

功能 數據類型
adata.X 矩陣數據 numpy,scipy sparse,matrix
adata.obs 觀察值數據 pandas dataframe
adata.var 特征和高可變基因數據 pandas dataframe
adata.uns 非結構化數據 dict

下面我們動手構建一個用於創建 AnnoData 的虛擬數據

import numpy as np
import pandas as pd
import anndata as ad
from string import ascii_uppercase

# 設置觀測值數量
n_obs = 1000
# 生成觀察時間
obs = pd.DataFrame()
obs['time'] = np.random.choice(['day 1', 'day 2', 'day 4', 'day 8'], n_obs)
# 設置特征名
var_names = [i*letter for i in range(1, 10) for letter in ascii_uppercase]
# 特征數量
n_vars = len(var_names)
# 特征注釋數據框
var = pd.DataFrame(index=var_names)
# 生成數據矩陣
X = np.arange(n_obs*n_vars).reshape(n_obs, n_vars)

2、AnnoData 初始化

# 初始化 AnnoData 對象
# AnnoData 對象默認使用數據類型為 `float32`, 可以更精確的存儲數據
# 這里設置為整數,為了演示方便
adata = ad.AnnData(X, obs=obs, var=var, dtype='int32')
# 一般默認將變量或特征存儲在數據框的行
# 查看數據
print(adata)
image.png
3、AnnoData 切片特性

可以看到 AnnData 具有和 dataframe 或 Array 相似的長相,同樣具備相似的特性,比如切片:

# 通過切片查看觀測值和變量
print(adata.obs_names[:10].tolist())
print(adata.obs_names[-10:].tolist())
print(adata.var_names[:10].tolist())
print(adata.var_names[-10:].tolist())
# 查看矩陣
print(X)

image.png

3、AnnoData 的 view 特性

AnnoData 可以實現與 numpy 中的 view 相似的功能。

換句話說就是,我們每次操作 AnnoData 時,並不是再新建一個 AnnoData 來存儲數據,而是直接找到已經之前初始化好的 AnnoData 的內存地址,通過內存地址來直接改變 AnnoData 的值。這樣做的好處是:

  • 無需分配多余的內存
  • 可以直接修改已經初始化后的 AnnoData 對象

view 可以使用 .copy() 來得到 AnnoData 對象。

# 查看 'A' 列的頭三個元素
print(adata[:3, 'A'].X)
# 設置 'A' 列的頭三個元素
adata[:3, 'A'].X = [0, 0, 0]
# 查看 'A' 列的頭五個元素
print(adata[:5, 'A'].X)
image.png

其實我們在調用 .[] 時,AnnoData已經在內部實現了該操作,也就是說該 view 會成為保存數據的 AnnoData 對象。

但是,如果將 AnnoData 對象的 view 中的一部分賦值,該內容會復制一份並生成新的數據存儲對象。

adata_subset = adata[:5, ['A', 'B']]
print(adata_subset)
adata_subset.obs['foo'] = range(5)
image.png

可以看到,這時賦值會直接將 AnnoData 對象復制一份。現在 adata_subset 會重新得到一塊內存用於存儲實際數據,而不再僅僅是對 adata 的內存地址引用。

4、備份到本地
# 計算對象大小的函數
def print_size_in_MB(x):
    print('{:.3} MB'.format(x.__sizeof__()/1e6))
# 查看 adata 對象大小
print_size_in_MB(adata)
# 查看是否備份
adata.isbacked
# 設置備份地址
adata.filename = './write/test.h5ad'
# 查看是否備份成功
adata.isbacked
image.png

可以看到,我們的 adata 對象已經備份成功,而且就在本地 './write/test.h5ad' 目錄。

前邊提到的 view 特性在這里同樣適用,我們來看看 adata_subset 是否備份成功。

adata_subset.isbacked
adata_subset.filename = './write/adata_subset_test.h5ad'
adata_subset.isbacked

image.png

adata_subset 並沒有被啟用備份模式,重新設置備份模式。

需要注意的是:備份僅影響數據矩陣 X,所有注釋信息都保留在內存中。如果想對全部數據的更改保存,則必須將導出到本地。

5、導出到本地

adata.write("./write/my_results.h5ad")
adata.write_csvs('./write/my_results_csvs', )

6、讀取數據

import scanpy as sc
import pandas as pd

# 初始化數據
adata = sc.read(filename)
# 加入數據
anno = pd.read_csv(filename_sample_annotation)
# 加入樣本分組信息
adata.obs['cell_groups'] = anno['cell_groups']  # categorical annotation of type pandas.Categorical
# 加入時間信息
adata.obs['time'] = anno['time']                # numerical annotation of type float
# 甚至可以直接賦值 dataframe
adata.obs = anno

官網:https://anndata.readthedocs.io/en/latest/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM