AnnData
Aperçu
AnnData est un package Python pour manipuler des matrices de données annotées, stockant les mesures expérimentales (X) aux côtés des métadonnées d'observation (obs), des métadonnées de variable (var) et des annotations multi-dimensionnelles (obsm, varm, obsp, varp, uns). Conçu à l'origine pour la génomique unicellulaire via Scanpy, il sert désormais de framework polyvalent pour toute donnée annotée nécessitant un stockage, une manipulation et une analyse efficaces.
Quand utiliser cette compétence
Utilisez cette compétence quand :
- Créer, lire ou écrire des objets AnnData
- Travailler avec les formats h5ad, zarr ou autres formats de données génomiques
- Effectuer une analyse d'ARNseq unicellulaire
- Gérer de grands ensembles de données avec matrices creuses ou mode backed
- Concaténer plusieurs ensembles de données ou lots expérimentaux
- Sous-ensembler, filtrer ou transformer des données annotées
- Intégrer avec scanpy, scvi-tools ou d'autres outils de l'écosystème scverse
Installation
uv pip install anndata
# Avec dépendances optionnelles
uv pip install anndata[dev,test,doc]
Démarrage rapide
Créer un objet AnnData
import anndata as ad
import numpy as np
import pandas as pd
# Création minimale
X = np.random.rand(100, 2000) # 100 cellules × 2000 gènes
adata = ad.AnnData(X)
# Avec métadonnées
obs = pd.DataFrame({
'cell_type': ['T cell', 'B cell'] * 50,
'sample': ['A', 'B'] * 50
}, index=[f'cell_{i}' for i in range(100)])
var = pd.DataFrame({
'gene_name': [f'Gene_{i}' for i in range(2000)]
}, index=[f'ENSG{i:05d}' for i in range(2000)])
adata = ad.AnnData(X=X, obs=obs, var=var)
Lire des données
# Lire un fichier h5ad
adata = ad.read_h5ad('data.h5ad')
# Lire avec mode backed (pour gros fichiers)
adata = ad.read_h5ad('large_data.h5ad', backed='r')
# Lire d'autres formats
adata = ad.read_csv('data.csv')
adata = ad.read_loom('data.loom')
adata = ad.read_10x_h5('filtered_feature_bc_matrix.h5')
Écrire des données
# Écrire un fichier h5ad
adata.write_h5ad('output.h5ad')
# Écrire avec compression
adata.write_h5ad('output.h5ad', compression='gzip')
# Écrire d'autres formats
adata.write_zarr('output.zarr')
adata.write_csvs('output_dir/')
Opérations basiques
# Sous-ensembler par conditions
t_cells = adata[adata.obs['cell_type'] == 'T cell']
# Sous-ensembler par indices
subset = adata[0:50, 0:100]
# Ajouter des métadonnées
adata.obs['quality_score'] = np.random.rand(adata.n_obs)
adata.var['highly_variable'] = np.random.rand(adata.n_vars) > 0.8
# Accéder aux dimensions
print(f"{adata.n_obs} observations × {adata.n_vars} variables")
Capacités principales
1. Structure de données
Comprendre la structure de l'objet AnnData incluant X, obs, var, layers, obsm, varm, obsp, varp, uns et les composants raw.
Voir : references/data_structure.md pour des informations complètes sur :
- Composants principaux (X, obs, var, layers, obsm, varm, obsp, varp, uns, raw)
- Créer des objets AnnData à partir de diverses sources
- Accéder et manipuler les composants de données
- Pratiques efficaces en mémoire
2. Opérations d'entrée/sortie
Lire et écrire des données dans différents formats avec support de la compression, du mode backed et du stockage cloud.
Voir : references/io_operations.md pour des détails sur :
- Formats natifs (h5ad, zarr)
- Formats alternatifs (CSV, MTX, Loom, 10X, Excel)
- Mode backed pour gros ensembles de données
- Accès à données distantes
- Conversion de formats
- Optimisation des performances
Commandes courantes :
# Lire/écrire h5ad
adata = ad.read_h5ad('data.h5ad', backed='r')
adata.write_h5ad('output.h5ad', compression='gzip')
# Lire données 10X
adata = ad.read_10x_h5('filtered_feature_bc_matrix.h5')
# Lire format MTX
adata = ad.read_mtx('matrix.mtx').T
3. Concaténation
Combiner plusieurs objets AnnData selon les observations ou les variables avec stratégies de jointure flexibles.
Voir : references/concatenation.md pour une couverture complète de :
- Concaténation basique (axis=0 pour observations, axis=1 pour variables)
- Types de jointure (inner, outer)
- Stratégies de fusion (same, unique, first, only)
- Tracer les sources de données avec labels
- Concaténation lazy (AnnCollection)
- Concaténation sur disque pour gros ensembles de données
Commandes courantes :
# Concaténer observations (combiner samples)
adata = ad.concat(
[adata1, adata2, adata3],
axis=0,
join='inner',
label='batch',
keys=['batch1', 'batch2', 'batch3']
)
# Concaténer variables (combiner modalités)
adata = ad.concat([adata_rna, adata_protein], axis=1)
# Concaténation lazy
from anndata.experimental import AnnCollection
collection = AnnCollection(
['data1.h5ad', 'data2.h5ad'],
join_obs='outer',
label='dataset'
)
4. Manipulation de données
Transformer, sous-ensembler, filtrer et réorganiser les données efficacement.
Voir : references/manipulation.md pour des conseils détaillés sur :
- Sous-ensembler (par indices, noms, masques booléens, conditions de métadonnées)
- Transposition
- Copie (copies complètes vs vues)
- Renommage (observations, variables, catégories)
- Conversions de type (chaînes en catégories, creux/dense)
- Ajouter/supprimer des composants de données
- Réordonner
- Filtrage du contrôle qualité
Commandes courantes :
# Sous-ensembler par métadonnées
filtered = adata[adata.obs['quality_score'] > 0.8]
hv_genes = adata[:, adata.var['highly_variable']]
# Transposer
adata_T = adata.T
# Copie vs vue
view = adata[0:100, :] # Vue (référence légère)
copy = adata[0:100, :].copy() # Copie indépendante
# Convertir chaînes en catégories
adata.strings_to_categoricals()
5. Bonnes pratiques
Suivre les modèles recommandés pour l'efficacité mémoire, les performances et la reproductibilité.
Voir : references/best_practices.md pour des conseils sur :
- Gestion de la mémoire (matrices creuses, catégories, mode backed)
- Vues vs copies
- Optimisation du stockage de données
- Optimisation des performances
- Travailler avec données raw
- Gestion des métadonnées
- Reproductibilité
- Gestion des erreurs
- Intégration avec d'autres outils
- Pièges courants et solutions
Recommandations clés :
# Utiliser matrices creuses pour données creuses
from scipy.sparse import csr_matrix
adata.X = csr_matrix(adata.X)
# Convertir chaînes en catégories
adata.strings_to_categoricals()
# Utiliser mode backed pour gros fichiers
adata = ad.read_h5ad('large.h5ad', backed='r')
# Stocker raw avant filtrage
adata.raw = adata.copy()
adata = adata[:, adata.var['highly_variable']]
Intégration avec l'écosystème Scverse
AnnData sert de structure de données fondatrice pour l'écosystème scverse :
Scanpy (Analyse unicellulaire)
import scanpy as sc
# Prétraitement
sc.pp.filter_cells(adata, min_genes=200)
sc.pp.normalize_total(adata, target_sum=1e4)
sc.pp.log1p(adata)
sc.pp.highly_variable_genes(adata, n_top_genes=2000)
# Réduction de dimensionnalité
sc.pp.pca(adata, n_comps=50)
sc.pp.neighbors(adata, n_neighbors=15)
sc.tl.umap(adata)
sc.tl.leiden(adata)
# Visualisation
sc.pl.umap(adata, color=['cell_type', 'leiden'])
Muon (Données multimodales)
import muon as mu
# Combiner données ARN et protéine
mdata = mu.MuData({'rna': adata_rna, 'protein': adata_protein})
Intégration PyTorch
from anndata.experimental import AnnLoader
# Créer DataLoader pour deep learning
dataloader = AnnLoader(adata, batch_size=128, shuffle=True)
for batch in dataloader:
X = batch.X
# Entraîner modèle
Workflows courants
Analyse d'ARNseq unicellulaire
import anndata as ad
import scanpy as sc
# 1. Charger données
adata = ad.read_10x_h5('filtered_feature_bc_matrix.h5')
# 2. Contrôle qualité
adata.obs['n_genes'] = (adata.X > 0).sum(axis=1)
adata.obs['n_counts'] = adata.X.sum(axis=1)
adata = adata[adata.obs['n_genes'] > 200]
adata = adata[adata.obs['n_counts'] < 50000]
# 3. Stocker raw
adata.raw = adata.copy()
# 4. Normaliser et filtrer
sc.pp.normalize_total(adata, target_sum=1e4)
sc.pp.log1p(adata)
sc.pp.highly_variable_genes(adata, n_top_genes=2000)
adata = adata[:, adata.var['highly_variable']]
# 5. Sauvegarder données traitées
adata.write_h5ad('processed.h5ad')
Intégration de lots
# Charger plusieurs lots
adata1 = ad.read_h5ad('batch1.h5ad')
adata2 = ad.read_h5ad('batch2.h5ad')
adata3 = ad.read_h5ad('batch3.h5ad')
# Concaténer avec labels de lot
adata = ad.concat(
[adata1, adata2, adata3],
label='batch',
keys=['batch1', 'batch2', 'batch3'],
join='inner'
)
# Appliquer correction de lot
import scanpy as sc
sc.pp.combat(adata, key='batch')
# Continuer l'analyse
sc.pp.pca(adata)
sc.pp.neighbors(adata)
sc.tl.umap(adata)
Travailler avec de gros ensembles de données
# Ouvrir en mode backed
adata = ad.read_h5ad('100GB_dataset.h5ad', backed='r')
# Filtrer basé sur métadonnées (sans charger données)
high_quality = adata[adata.obs['quality_score'] > 0.8]
# Charger sous-ensemble filtré
adata_subset = high_quality.to_memory()
# Traiter sous-ensemble
process(adata_subset)
# Ou traiter par chunks
chunk_size = 1000
for i in range(0, adata.n_obs, chunk_size):
chunk = adata[i:i+chunk_size, :].to_memory()
process(chunk)
Dépannage
Erreurs de mémoire insuffisante
Utilisez le mode backed ou convertissez en matrices creuses :
# Mode backed
adata = ad.read_h5ad('file.h5ad', backed='r')
# Matrices creuses
from scipy.sparse import csr_matrix
adata.X = csr_matrix(adata.X)
Lecture de fichiers lente
Utilisez la compression et les formats appropriés :
# Optimiser pour stockage
adata.strings_to_categoricals()
adata.write_h5ad('file.h5ad', compression='gzip')
# Utiliser Zarr pour stockage cloud
adata.write_zarr('file.zarr', chunks=(1000, 1000))
Problèmes d'alignement d'index
Toujours aligner données externes sur l'index :
# Incorrect
adata.obs['new_col'] = external_data['values']
# Correct
adata.obs['new_col'] = external_data.set_index('cell_id').loc[adata.obs_names, 'values']
Ressources supplémentaires
- Documentation officielle : https://anndata.readthedocs.io/
- Tutoriels Scanpy : https://scanpy.readthedocs.io/
- Écosystème Scverse : https://scverse.org/
- Dépôt GitHub : https://github.com/scverse/anndata