Chatomics Field GuideWhat They Don't Teach You

Comparison · integration

Seurat CCA integration vs Seurat RPCA integration: Which One Should You Use?

Both run through the same FindIntegrationAnchors framework, but they disagree on how willing they are to call two cells from different batches "the same cell."

By Ming "Tommy" Tang, Director of Bioinformatics in Big Pharma · Reviewed September 2026 · 4 min read

The verdict

Default to RPCA. For the typical reader here, integrating multiple scRNA-seq samples from the same platform, often 10x Genomics lanes run across different days or patients, RPCA is faster, scales to the six-figure cell counts that modern atlases reach, and is meaningfully less likely to merge biologically distinct populations that happen to look similar after correction. That last point matters more than speed: an over-merged UMAP looks fine until you go looking for a rare population that quietly got folded into a bigger cluster. Seurat's own documentation now steers users toward RPCA for exactly this reason when batches are large or when you expect a substantial fraction of cells in one dataset to have no match in the other.

Reach for CCA when the biology demands stronger correction than RPCA's mutual-neighbor constraint allows: cross-species integration, cross-modality integration (scRNA-seq with CITE-seq or ATAC-derived gene activity scores), or any case where you're confident the same cell types are present in both datasets but technical or biological factors have shifted expression substantially. In those situations RPCA's stricter anchors will simply fail to pair cells that a human would call the same type, and CCA's willingness to search for correlated structure across a bigger gap is the feature, not the bug.

CCA and RPCA are both anchor-based integration methods in Seurat, and they share the same overall pipeline: find anchors between datasets, then use those anchors to correct expression values. Where they differ is the space in which anchors get identified, and that difference changes how aggressively each method merges cells.

CCA (canonical correlation analysis) solves a generalized eigenvalue problem on the covariance matrices of the two datasets, finding linear combinations of genes whose cell embeddings correlate across datasets. Seurat then L2-normalizes those canonical variates to stabilize the comparison before calling anchors. This is powerful because it actively searches for shared correlated structure even when the datasets look very different on the surface, but that same power is what lets it merge cell types that shouldn't be merged.

RPCA (reciprocal PCA) skips the shared correlated subspace entirely. It runs PCA on each dataset separately, then projects each dataset into the other's PCA space and only accepts an anchor when the pairing is a mutual nearest neighbor in both directions. That mutual-neighbor constraint is stricter than what CCA requires, so RPCA finds fewer anchors and is less likely to force alignment between cells that are genuinely different. It's also cheaper to compute, since you're not solving for a new joint subspace.

Head to head

CriterionSeurat CCA integrationSeurat RPCA integrationEdge
Anchor projection spaceAnchors are found in a shared canonical-correlation subspace built by solving a generalized eigenvalue problem on both datasets' covariance matrices.Anchors are found by projecting each dataset into the other's own PCA space, with a mutual-neighbor requirement in both directions.Tie
Different mechanisms by design, not a quality gap.
Over-merging riskProne to overcorrection when a large share of cells are non-overlapping across datasets, which can merge biologically distinct cell types.More conservative; cells in different biological states are less likely to be forced into alignment.Seurat RPCA integration
Speed and memory on large datasets (>100k cells)Slow and memory-intensive at this scale.Scales noticeably better; recommended alongside Harmony for large datasets.Seurat RPCA integration
Partially overlapping cell populations across batchesNot the intended use case; can inappropriately merge cell types present in only one dataset.Explicitly recommended when a substantial fraction of cells in one dataset have no matching type in the other.Seurat RPCA integration
Cross-species or cross-modality integrationBetter suited when shared features show substantial expression shifts, as in cross-species or cross-modality comparisons.Not recommended for these scenarios; the mutual-neighbor constraint is too strict to bridge large expression shifts.Seurat CCA integration
Setup complexityUses the default reduction in FindIntegrationAnchors with no extra prerequisite steps.Requires running PCA on each dataset or layer individually before integration, and setting reduction = 'rpca' (or method = RPCAIntegration in v5) explicitly.Seurat CCA integration
CCA is the path of least resistance to set up; that convenience is also why people end up on it by default without evaluating fit.
k.anchor default behaviorDefault k.anchor = 5; raising it to 20 increases alignment aggressiveness.Default k.anchor = 5, but the same value yields more conservative alignment due to the mutual-neighbor constraint already built in.Tie
Benchmark ranking (Luecken et al. 2021, 16 methods, up to 1M cells)Performed well specifically on biology-conservation metrics.Ranked second overall behind scANVI, ahead of CCA and scVI on the composite score.Seurat RPCA integration
Seurat v5 APIAvailable via IntegrateLayers(method = CCAIntegration, orig.reduction = 'pca', new.reduction = 'integrated.cca').Available via IntegrateLayers(method = RPCAIntegration, orig.reduction = 'pca', new.reduction = 'integrated.rpca').Tie
Fit for same-platform batches (e.g. multiple 10x lanes)Not the documented recommendation for this scenario; more correction than needed can distort within-platform variation.Explicitly recommended for datasets from the same platform.Seurat RPCA integration

Use Seurat CCA integration when

  • You're integrating across species and need to align shared orthologous genes despite large expression-level differences.
  • You're integrating across modalities, such as scRNA-seq with CITE-seq protein data, where the correction needs to bridge a bigger technical gap.
  • Cell types are well conserved across your datasets, but the batches differ strongly in overall expression scale or come from very different protocols.
  • Your dataset is small enough that CCA's runtime and memory cost aren't a practical concern, and you want the strongest available correction.

Use Seurat RPCA integration when

  • You're merging multiple runs or lanes from the same platform, such as several 10x Genomics captures from the same study.
  • A substantial fraction of cells in one dataset have no matching cell type in the other, and you want to avoid forcing a match.
  • Your combined dataset is large, on the order of 100,000+ cells, where CCA becomes slow and memory-hungry.
  • You've seen CCA merge clusters you believe are biologically distinct and want a more conservative default.
  • You're integrating many samples and need integration to finish in a reasonable amount of time as part of a routine pipeline.

Switching between them

Switching from CCA to RPCA is not a one-argument change. You must run RunPCA on each dataset or layer individually before calling FindIntegrationAnchors or IntegrateLayers, since RPCA needs each dataset's own PCA embedding (orig.reduction = 'pca') to project into. In the classic workflow, set reduction = 'rpca' explicitly in FindIntegrationAnchors, since the function defaults to CCA if you leave it unset. In Seurat v5, swap CCAIntegration for RPCAIntegration in IntegrateLayers and expect the output reduction name to change (integrated.cca vs integrated.rpca), so update any downstream code that references it by name.

Anchor counts will typically drop after switching to RPCA, because its mutual-neighbor requirement is stricter than CCA's correlated-subspace search; this is expected, not a bug. If clusters look under-integrated after the switch, don't assume RPCA is broken, first try raising k.anchor from the default of 5 toward 20 rather than reverting to CCA. There is no published numeric threshold for translating a CCA-tuned k.anchor or k.filter value directly into an equivalent RPCA setting, so re-tune empirically on your own data rather than copying parameters across methods.

Pitfalls with either

  • Calling FindIntegrationAnchors without setting reduction = 'rpca' and assuming you're running RPCA; the function defaults to CCA, so check the argument explicitly.
  • Running RPCAIntegration in IntegrateLayers without first running RunPCA on each dataset or layer individually; RPCA needs that per-dataset PCA as orig.reduction before it can project datasets into each other's space.
  • Using CCA on datasets where you expect many cell types to be present in only one batch, then being surprised when distinct populations merge; switch to RPCA when overlap between batches is expected to be partial.
  • Copying a k.anchor value tuned for a CCA pipeline directly into an RPCA run; the same value behaves more conservatively under RPCA because of its mutual-neighbor constraint, so re-tune it on your own data.
  • Running CCA integration on an atlas-scale dataset above roughly 100,000 cells and hitting memory or runtime walls; switch to RPCA or Harmony once you're at that scale.
  • Assuming RPCA is unconditionally the better method because it ranks higher in one benchmark's composite score; CCA still scores well on biology-conservation metrics specifically, so match the method to whether your batches share cell types cleanly or only partially.

Questions people ask

Is RPCA always better than CCA in Seurat?

No. RPCA is faster and more conservative, which is what you want when batches partially overlap or datasets are large, but CCA's stronger correction is genuinely useful for cross-species or cross-modality integration where expression differences are large even among shared cell types. In the Luecken et al. 2021 Nature Methods benchmark, RPCA ranked ahead of CCA on the composite score across 16 methods and 13 datasets, but CCA still scored well on biology-conservation metrics specifically, so the choice depends on what you're optimizing for.

When should I use CCA instead of RPCA?

Use CCA when cell types are conserved across datasets but gene expression differs substantially between them, which is common in cross-species integration or when integrating across assay types (for example scRNA-seq with CITE-seq). CCA is built to find correlated structure even under those larger expression shifts, which RPCA's stricter anchor requirement is not designed to handle.

How do I switch an existing CCA pipeline to RPCA?

In Seurat v5, swap CCAIntegration for RPCAIntegration inside IntegrateLayers, but first run RunPCA on each dataset or layer individually since RPCA needs each dataset's own PCA space as orig.reduction. In the older FindIntegrationAnchors workflow, set reduction = 'rpca' explicitly, since the function defaults to CCA if you don't.

Does RPCA work for cross-species integration?

Not well. Seurat's own documentation recommends CCA for cross-species or cross-modality scenarios with substantial expression shifts, and specifically does not recommend RPCA for those cases. RPCA's mutual-neighbor anchor requirement is too strict to reliably pair cells when the underlying feature space has shifted that much.

What is k.anchor and how does it differ between CCA and RPCA?

k.anchor controls how many neighbors are used when scoring anchors in FindIntegrationAnchors, with a default of 5 for both methods. Because RPCA's mutual-neighbor constraint is already stricter than CCA's, the same k.anchor value produces a more conservative result under RPCA; increasing k.anchor toward 20 is the standard way to force more aggressive alignment under either method if you find batches are under-integrated.

Related pages

Related reading on the blog

Sources

  1. Fast integration using reciprocal PCA (RPCA) — Source for RPCA's mutual-neighbor anchor requirement, when to prefer it over CCA, and the k.anchor parameter
  2. Integrative analysis in Seurat v5 — Source for the IntegrateLayers/CCAIntegration/RPCAIntegration workflow and the requirement to run PCA per dataset first
  3. How CCA alignment and cell label transfer work in Seurat — Source for the CCA covariance-matrix and L2 normalization mechanics
  4. Benchmarking atlas-level data integration in single-cell genomics — Source for the 16-method benchmark ranking RPCA above CCA overall, with CCA scoring well on biology conservation