Skip to main content
v2026.11,858 entries · CC-BY 4.0

PCA in Python (scikit-learn): Scaling and Reading Output

Run PCA in Python with scikit-learn, decide whether to scale first, choose n_components and read every output attribute, with a worked iris example.

Written and maintained by CASRAI Editorial Board

Last updated

Who this is for: researchers and analysts who have a numeric table (samples in rows, measured variables in columns) and need to run principal component analysis (PCA) with scikit-learn in Python, decide whether to scale first, and read the output correctly.

In scikit-learn, PCA is sklearn.decomposition.PCA. It centres each feature but does not scale it before the singular value decomposition (SVD), so unscaled columns with large variance dominate the result. The sections below give the install, a complete runnable example on the iris data, the scaling decision with measured numbers, a table for reading every attribute, troubleshooting and alternatives. Documentation checked 2026-11-07 against scikit-learn 1.9.1.

What PCA in Python is used for in research

PCA projects a data matrix onto a smaller number of orthogonal directions (principal components) ordered by the variance they capture. Researchers use it to summarise many correlated measurements, to inspect structure before clustering (see k-means clustering) and to reduce the columns of high-dimensional data before modelling. It works from the covariance structure of the variables. If you work in R instead, see PCA in R with prcomp.

Install or access (official source only)

The scikit-learn installation page (scikit-learn.org/stable/install.html) gives two routes: pip install -U scikit-learn, or a conda environment from conda-forge:

conda create -n sklearn-env -c conda-forge scikit-learn
conda activate sklearn-env

PCA ships inside scikit-learn; no separate package is needed. Check your version with import sklearn; print(sklearn.__version__), and read the documentation for that version if yours is older than 1.9.

Step-by-step: PCA with scikit-learn

This runs on the iris table that ships with scikit-learn, so every command is reproducible without a download. The numbers shown in this guide were produced by running this code with scikit-learn 1.9.

  1. Load the data as a table. from sklearn.datasets import load_iris, then X = load_iris(as_frame=True).data. This gives 150 rows and four columns: sepal length, sepal width, petal length and petal width, all in centimetres.
  2. Decide on scaling. PCA centres but does not scale, so put a StandardScaler in front when your columns are in different units or have very different spreads (the next section shows why).
  3. Build and fit a pipeline. from sklearn.decomposition import PCA, from sklearn.preprocessing import StandardScaler, from sklearn.pipeline import make_pipeline, then pipe = make_pipeline(StandardScaler(), PCA(n_components=2)) and scores = pipe.fit_transform(X). fit_transform returns an array of shape (n_samples, n_components), here 150 by 2.
  4. Read the fitted PCA step. pca = pipe[-1], then pca.explained_variance_ratio_, pca.components_ and pca.singular_values_ (interpreted in the output table below).
  5. Project new observations. pipe.transform(X_new) projects them onto the components previously extracted from the training set. Fit on training data only and call transform on anything held out, so the centring, scaling and components never see the held-out rows.
  6. Plot. The columns of scores are the component scores; a scatter plot of column 0 against column 1 in matplotlib is the usual first view. A scree plot of explained_variance_ratio_ shows how many components matter.

Choosing n_components

The n_components argument accepts an integer (keep that many components), a float between 0 and 1 (keep as many components as needed to reach that share of variance, which requires svd_solver='full'), or 'mle' (Minka’s maximum-likelihood estimate of dimensionality, also with the full solver). For example, PCA(n_components=0.95, svd_solver='full') on the scaled iris data keeps 2 components.

Scaling changes the answer: measured on iris

Running the same data both ways with two components gives clearly different results.

Setting explained_variance_ratio_ (PC1, PC2) Largest loadings on PC1
PCA on raw columns 0.9246, 0.0531 petal length (0.8567)
StandardScaler, then PCA 0.7296, 0.2285 petal length (0.5804), petal width (0.5649), sepal length (0.5211)

Without scaling, PC1 is dominated by petal length, the column with the largest spread, so the 92 percent figure partly reflects units rather than structure. After standardising, three variables contribute similarly to PC1. Which is right depends on your question; when variables are measured on different scales, standardising is the common choice. That is an editorial judgement, not a scikit-learn rule: the library only documents that it centres and does not scale.

Output and how to read it

These attributes come from the PCA reference page for scikit-learn 1.9.1. The values in the last column are from the scaled iris run above.

Attribute or method What it holds Scaled iris result
components_ Array of shape (n_components, n_features): each row is one principal axis, sorted by decreasing explained_variance_. Row 0: 0.5211, -0.2693, 0.5804, 0.5649
explained_variance_ Variance along each component, estimated with n_samples – 1 degrees of freedom. 2.9381, 0.9202
explained_variance_ratio_ Share of total variance carried by each component. 0.7296, 0.2285
singular_values_ Singular values corresponding to each kept component. 20.9231, 11.7092
mean_ Per-feature mean, equal to X.mean(axis=0); it is what was subtracted when centring. Not applicable: it is the mean of the standardised data, which is zero
n_components_ The number of components actually kept. 2
transform(X) / fit_transform(X) Projection onto the components; shape (n_samples, n_components). 150 by 2
inverse_transform(Z) Maps component scores back to the original feature space. Not exact when components are dropped

The documentation’s own small example uses X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]]); PCA(n_components=2).fit(X) gives explained_variance_ratio_ of [0.9924, 0.0075] and singular_values_ of [6.30061, 0.54980].

Where the eigenvalues are

Searchers often ask for sklearn PCA eigenvalues. scikit-learn exposes the variances along the components as explained_variance_, with the matching directions in components_. There is no attribute literally named eigenvalues.

svd_solver and other arguments

svd_solver Documented behaviour
'auto' (default) Uses covariance_eigh when there are fewer than 1000 features and more than 10 times as many samples as features; otherwise randomized when the data is larger than 500 by 500 and n_components is below 80 percent of the smaller dimension; otherwise full.
'full' Required for a float n_components and for 'mle'.
'covariance_eigh' Efficient when n_samples is much larger than n_features; the documentation notes it effectively doubles the condition number.
'arpack' Requires 0 < n_components < min(X.shape).
'randomized' inverse_transform is not the exact inverse even with whiten=False.

Other arguments: whiten=True scales each component to unit variance, which the user guide describes as useful for downstream estimators that assume isotropy such as an RBF-kernel SVM or k-means; random_state is the seed argument of the signature.

Troubleshooting

  • Float n_components is rejected or ignored. A value between 0 and 1 is a variance threshold and needs svd_solver='full'; set it explicitly.
  • arpack raises an error on n_components. It needs n_components strictly between 0 and min(X.shape).
  • Sparse input fails. Sparse matrices are accepted only by some solvers such as 'arpack' and 'covariance_eigh'. TruncatedSVD is the documented alternative, but it does not centre the data, so its results differ from PCA.
  • Reconstruction does not match the input. With the randomized solver inverse_transform is not exact, and dropping components loses information by design.
  • Data does not fit in memory. PCA needs all data in memory; IncrementalPCA with partial_fit processes chunks.
  • Results look driven by one variable. Check whether you forgot to scale (see the comparison above).

Free alternatives and related estimators

Option Use it when (per scikit-learn user guide)
IncrementalPCA The data is too large for memory; fit with partial_fit on chunks.
KernelPCA The structure is nonlinear. It supports transform and inverse_transform, the inverse being an approximation; it uses eigen_solver rather than svd_solver.
SparsePCA / MiniBatchSparsePCA You want sparse components; alpha controls the L1 penalty.
TruncatedSVD The input is sparse and should not be centred.
prcomp in R You work in R rather than Python.

FAQ

What is sklearn PCA and how do I run it?

It is the PCA class in sklearn.decomposition. Create PCA(n_components=k), call fit_transform(X), and read explained_variance_ratio_ and components_.

Does sklearn PCA standardise my data?

No. The documentation states the input is centred but not scaled for each feature before the SVD. Add StandardScaler in a pipeline if you need scaling.

How many components should I keep?

scikit-learn offers an integer, a variance fraction (with the full solver) or 'mle'. Which to use is an analytic decision; a scree plot of the explained variance ratios is a common aid.

What does fit_transform return?

An array of shape (n_samples, n_components) holding each sample’s scores on the components.

Where are the sklearn PCA components and eigenvalues?

components_ holds one component per row, sorted by decreasing explained_variance_; explained_variance_ holds the corresponding variances.

What is Kernel PCA?

KernelPCA is scikit-learn’s nonlinear variant; its inverse_transform is an approximation.

Sources (official documentation)

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about PCA in Python (scikit-learn): Scaling and Reading Output

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →