scanpy.pp.bbknn#

scanpy.pp.bbknn(adata, neighbors_within_batch=3, n_pcs=None, *, batches='obs.batch', use=None, transformer=None, metric='euclidean', metric_kwds=mappingproxy({}), trim=None, rng=None, out=False)[source]#

Compute a batch balanced neighborhood graph of observations [Polański et al., 2019].

Batch balanced kNN alters the kNN procedure to identify each cell’s top neighbors in each batch separately instead of the entire cell pool with no accounting for batch. The nearest neighbors of each batch are then merged to create a final list of neighbors for the cell, which aligns batches in a quick and lightweight manner.

Use this as an alternative to neighbors(): it writes the same fields, so all downstream steps (e.g. umap() or leiden()) work unchanged. This CPU implementation is based on the rapids-singlecell package.

Array type support#

Array type

supported

… experimentally in dask Array

numpy.ndarray

✅

❌

scipy.sparse.{csr,csc}_{array,matrix}

✅

❌

Parameters:
adata AnnData

Annotated data matrix.

neighbors_within_batch int (default: 3)

How many top neighbors to report for each batch. The total number of neighbors is this number times the number of batches, which then serves as the basis for the construction of a symmetrical matrix of connectivities.

n_pcs int | None (default: None)

Use this many PCs. If n_pcs==0 use .X if use is None.

batches AdRef | str (default: 'obs.batch')

The annotation discriminating between the batches, e.g. A.obs['batch']. strs are anndata.acc.AdAcc.resolve()d, e.g. 'obs.batch'.

use LayerAcc | MultiAcc | str | None (default: None)

Use the indicated representation: a LayerAcc (e.g. A.X, A.layers[...]) or MultiAcc (e.g. A.obsm[...]). strs are resolve()d, e.g. 'obsm.pca'.

If None, the representation is chosen automatically: For .n_vars < N_PCS (default: 50), .X is used, otherwise the PCA representation (.obsm['X_pca'], or .obsm['pca'] if it was computed under ScanpyV2Preview). If it is not present, it’s computed with default parameters or n_pcs if present.

transformer KnnTransformerLike | Literal['pynndescent', 'sklearn'] | None (default: None)

kNN search backend following the API of KNeighborsTransformer. One index is built per batch and queried with all observations, so its n_neighbors is ignored in favor of neighbors_within_batch. See Using other kNN libraries in Scanpy for more details. Also accepts the following known options:

None (the default)

Behavior depends on data size. For small data, we will calculate exact kNN, otherwise we use PyNNDescentTransformer

'pynndescent'

PyNNDescentTransformer

metric Literal['cityblock', 'cosine', 'euclidean', 'l1', 'l2', 'manhattan'] | Literal['braycurtis', 'canberra', 'chebyshev', 'correlation', 'dice', 'hamming', 'jaccard', 'kulsinski', 'mahalanobis', 'minkowski', 'rogerstanimoto', 'russellrao', 'seuclidean', 'sokalmichener', 'sokalsneath', 'sqeuclidean', 'yule'] | Callable[[ndarray, ndarray], float] (default: 'euclidean')

A known metric’s name or a callable that returns a distance.

ignored if transformer is an instance.

metric_kwds Mapping[str, Any] (default: mappingproxy({}))

Options for the metric.

ignored if transformer is an instance.

trim int | None (default: None)

Trim each cell’s neighbors to these many top connectivities. May help with population independence and improve the tidiness of clustering. The lower the value, the more independent the individual populations, at the cost of a more conserved batch effect. If None, this is set to 10 times the total number of neighbors. Set to 0 to skip trimming.

rng int | integer | Sequence[int] | SeedSequence | Generator | BitGenerator | None (default: None)

Random number generation to control stochasticity.

If a type:SeedLike value, it’s used to seed a new random number generator; If a numpy.random.Generator, rng’s state will be directly advanced; If None, a non-reproducible random number generator is used. See numpy.random.default_rng() for more details.

The default value matches legacy scanpy behavior and will change to None in scanpy 2.0.

ignored if transformer is an instance.

out GraphAcc | str | NeighborsOut | bool (default: False)

Where to write the outputs. A single accessor writes connectivities to it and names the others after its key k: k in kinds of places no other output goes to, else k_{name}, e.g. .obsp['k_distances'] next to .obsp['k']. Outputs that aren’t written by default stay unwritten. A mapping from output names to accessors writes only the outputs it names, each to a different place, e.g. {'connectivities': A.obsp['conns']}. strs are anndata.acc.AdAcc.resolve()d. The uns entry is named after connectivities’s key, so a mapping has to include connectivities. If True, they are returned as a NeighborsResult instead of written. If False, they are written to their default locations. The outputs are:

connectivities

The weighted adjacency matrix. By default written to A.obsp['connectivities'].

distances

The distance matrix. By default written to A.obsp['distances'].

Return type:

NeighborsResult | None

Returns:

Returns the outputs if out=True, else None. By default sets the following fields (see out for others):

adata.obsp['connectivities']scipy.sparse.csr_matrix (dtype float)

Weighted adjacency matrix of the neighborhood graph of data points. Weights should be interpreted as connectivities.

adata.obsp['distances']scipy.sparse.csr_matrix (dtype float)

Distance matrix of the batch balanced nearest neighbors search. Each row (cell) has neighbors_within_batch × n_batches - 1 non-zero entries: its nearest neighbors in each batch, excluding the cell itself.

adata.uns['neighbors']dict

neighbors parameters, and the .obsp keys the matrices were written to.

Examples

>>> import scanpy as sc
>>> adata = sc.datasets.pbmc68k_reduced()
>>> adata.obs["batch"] = adata.obs["phase"]
>>> sc.pp.bbknn(adata, batches="obs.batch")
>>> sc.tl.umap(adata)