跳至内容

R 中的 PCA:逐步教程与示例

通过本教程掌握在 R 中应用 PCA。规范化数据、使用 princomp() 计算主成分,并通过碎石图和双标图可视化结果。
已更新 2026年10月6日  · 15分钟 阅读

使用 AI 探索

ChatGPTClaudePerplexity

R 中的 PCA 分析

主成分分析(PCA)简介

设想您是一名零售行业的数据科学家,正试图从包含以下五个特征的数据集中理解是什么让客户感到满意:月度花费、年龄、性别、购买频率以及产品评分。为了更好地分析并得出可操作的结论,我们需要理解数据集,或者至少对其进行可视化。人类很难直观想象三维以上的空间,因此将包含五个特征(维度)的客户数据可视化并不直观。这正是主成分分析(简称 PCA)派上用场的地方。

“那么,什么是主成分分析?”

这是一种统计方法,可用于分析高维数据,并从中提取最重要的信息。其做法是将原始数据转换到一个更低维的空间,同时将高度相关的变量聚合在一起。在我们的场景中,PCA 可能会选择三个特征,比如月度花费、购买频率和产品评分。这样可以更容易地对数据进行可视化和理解。

在本教程中,我将讲解主成分分析的关键概念,并演示如何使用 R 中的 corrr 包将其应用于真实场景。

观看课程视频,进一步了解 R 中的主成分分析

要点速览

  • PCA 将高维数据降至更少的维度,同时尽可能保留方差
  • 在运行 PCA 前,务必使用 scale() 对数据进行规范化,以确保各变量贡献相同
  • 在 R 中使用 princomp() 或 prcomp(),并结合 FactoMineR 和 factoextra 包进行分析与可视化
  • 前两个主成分通常可解释 80–90% 的方差,常常足以用于可视化
  • 使用碎石图决定保留的成分数,用双标图解读变量关系

先决条件

要跟随本教程,您需要:

  • 具备基础 R 编程知识——如需复习,请参阅 Tidyverse 入门 教程
  • 熟悉在 R 中加载数据框并进行子集操作
  • 已安装 R 4.x 或更高版本
  • 以下软件包:corrr、ggcorrplot、FactoMineR、factoextra(安装步骤在教程中讲解)

PCA 如何运作?5 步指南

尽管我们的重点是 PCA,但请牢记以下五种旨在总结与可视化多变量数据的主成分方法。与其他方法不同,PCA 仅适用于定量变量。 

主成分方法

主成分方法

我们不深入讲解数学原理,因为它可能较为复杂。然而,理解以下五个步骤有助于更好地把握如何计算 PCA。 

计算主成分的五个主要步骤

计算主成分的五个主要步骤

步骤 1 - 数据规范化

回到引言中的例子,设想某位客户具有如下信息。 

  • 月度花费:$300
  • 年龄:27
  • 评分:4.5

这些信息的量纲不同,直接用此数据进行 PCA 会产生偏差。这时需要进行数据规范化。它确保每个属性具有相同的贡献度,避免某个变量支配其他变量。对每个变量,规范化通过减去其均值并除以其标准差来完成。   

步骤 2 - 协方差矩阵

顾名思义,此步骤基于规范化后的数据计算协方差矩阵。这是一个对称矩阵,其中每个元素 (i, j) 对应变量 i 与 j 之间的协方差。

步骤 3 - 特征向量与特征值

从几何角度看,特征向量表示一个方向,比如“竖直”或“90 度”。而特征值是一个数,表示数据在该方向上的方差大小。每个特征向量都有其对应的特征值。 

步骤 4 - 主成分的选择

特征向量与特征值的配对数量等于数据中的变量数。在只包含月度花费、年龄和评分的数据中,将会有三对。并非所有配对都重要。因此,具有最大特征值的特征向量对应第一主成分。第二主成分则对应于具有第二大特征值的特征向量,依此类推。

步骤 5 - 在新维度空间中的数据变换

此步骤将原始数据重新投影到由主成分定义的新子空间中。该重投影通过将原始数据与此前计算的特征向量相乘来完成。

需要牢记的是,此变换并未修改原始数据本身,而是提供了一个新的视角,以更好地表征数据。 

主成分分析的应用 

主成分分析在我们的日常生活中有广泛应用,包括但不限于金融、图像处理、医疗与安防等领域。

金融

利用历史价格预测股票价格的思想在研究中已沿用多年。PCA 可用于降维与数据分析,帮助专家找到解释数据大部分变异性的相关成分。您可以在我们的专门课程中进一步学习R 中的降维。 

图像处理

一张图像由多个特征构成。PCA 主要用于图像压缩,在降低维度的同时保留图像的关键信息。此外,PCA 还可用于更复杂的任务,例如图像识别。   

医疗

与图像压缩的逻辑相同,PCA 被用于核磁共振成像(MRI)中,以降低图像的维度,从而获得更好的可视化与医学分析。它也可集成到医学技术中,例如基于影像识别特定疾病。

安防

用于指纹识别的生物识别系统可以集成基于主成分分析的技术,以提取最相关的特征,如指纹纹理及其他信息。 

R 中的 PCA 实战示例

现在您已经理解了 PCA 的基本原理,终于可以看看它的实际应用。

本节涵盖从安装相关软件包、加载并准备数据、在 R 中应用主成分分析,到解读结果的全部步骤。 

源代码可在 DataLab 获取。

环境配置 

要顺利完成本教程,您需要以下库;每个库要高效使用通常需两步: 

  • 安装库以获取全部函数。
  • 加载库以便使用这些函数。

R 中的 corrr 包

这是一个用于相关性分析的 R 包,主要专注于创建与处理 R 数据框。以下为安装与加载步骤。 

install.packages("corrr")
library('corrr')

R 中的 ggcorrplot 包

ggcorrplot 包提供多种函数,其中包括与 ggplot2 搭配的函数,便于可视化相关矩阵。与上述步骤类似,安装十分直接。

install.packages("ggcorrplot")
library(ggcorrplot)

R 中的 FactoMineR 包

主要用于多变量探索性数据分析;factoMineR 包提供 PCA 模块以执行主成分分析。 

install.packages("FactoMineR")
library("FactoMineR")

R 中的 factoextra 包

最后这个包提供了可视化主成分分析结果的相关函数。包括但不限于碎石图、双标图——本文稍后将介绍这两种可视化技术。

install.packages("factoextra")
library(factoextra)

探索数据

在加载数据并进行进一步探索之前,先了解您将要处理的数据及其基本信息是很有必要的。  

蛋白质数据

该蛋白质数据集为实值多变量数据,描述了 25 个欧洲国家居民的平均蛋白质摄入量。 

每个国家有十列。前八列对应不同类型的蛋白质。最后一列对应各蛋白质平均值的总和。

我们先快速浏览一下数据。 

首先,使用 read.csv() 函数加载数据,然后用 str(),如下图所示。 

protein_data <- read.csv("protein.csv")
str(protein_data)

可以看到数据集有 25 条观测与 11 列。除 Country 列为字符型外,其余各变量均为数值型。 

蛋白质数据描述

蛋白质数据描述

检查空值 

缺失值的存在会使 PCA 结果产生偏差。因此,强烈建议采用合适的方法处理这些值。我们的数据科学家应掌握的缺失值处理技巧教程可帮助您做出正确选择。 

colSums(is.na(protein_data))

colSums() 与 is.na() 结合可返回每列中的缺失值数量。如下所示,没有列存在缺失值。

各列缺失值数量

各列缺失值数量

数据规范化

如本文前面所述,PCA 只适用于数值型变量。因此我们需要去除 Country 列。此外,Total 列为剩余数值变量的线性组合,对分析并无帮助。

下面的代码创建仅包含数值列的新数据。

numerical_data <- protein_data[,2:10]

head(numerical_data)

数据规范化前

数据规范化前(仅展示前五列)

现在,可使用 scale() 函数进行规范化。

data_normalized <- scale(numerical_data)
head(data_normalized)

规范化后的数据

规范化后的数据(仅展示前五列)

可视化相关矩阵

在运行 PCA 之前,通过可视化变量间的相关性可以验证 PCA 是否会有效。高相关性表明存在冗余,PCA 可以对其进行压缩。我将使用前面安装的 corrr 与 ggcorrplot 包。

corr_matrix <- cor(data_normalized)
ggcorrplot(corr_matrix,
           hc.order = TRUE,
           type = "lower",
           lab = TRUE)

热图显示动物蛋白来源(红肉、白肉、鸡蛋和牛奶)之间存在强正相关,这也解释了第一个主成分几乎捕获了 77% 的总方差。这种相关结构正是 PCA 旨在利用的。

关于 R 中 PCA 函数的说明:本教程使用 princomp(),它对协方差矩阵进行谱分解。对于大多数实际场景,prcomp() 更为常用——它使用奇异值分解(SVD),在变量较多的数据集上数值稳定性更好。两者输出的一个关键差异:princomp() 将载荷存放在 $loadings,而 prcomp() 使用 $rotation。对于像本文所用蛋白质数据这类条件良好的数据,它们得到的结果等价。

应用 PCA

现在执行 PCA 所需的一切资源都已就绪。首先用 princomp() 计算 PCA,再用 summary() 查看结果。

data.pca <- princomp(data_normalized)
summary(data.pca)

R PCA 摘要

R PCA 摘要 

从上图可以看到,生成了 9 个主成分(Comp.1 至 Comp.9),这也对应于数据中的变量数量。

每个成分解释了数据集中总方差的一定比例。在累计占比一栏,第一主成分解释了将近 77% 的总方差。这意味着在 9 个变量构成的数据中,近三分之二的信息可以仅由第一主成分表示。第二主成分解释了 12.08% 的总方差。 

Comp.1 与 Comp.2 的累计占比接近 89% 的总方差。这表示前两个主成分已足以较好地表示数据。 

有了前两个主成分固然很好,但它们究竟意味着什么? 

可以通过查看各主成分的载荷与每一列的关系来回答这个问题。 

data.pca$loadings[, 1:2]

前两个主成分的载荷矩阵

前两个主成分的载荷矩阵

载荷矩阵显示,第一主成分在红肉、白肉、鸡蛋与牛奶上具有较高的正值。然而,在谷物、豆类、坚果与油籽以及果蔬上的数值相对为负。这表明动物蛋白摄入更高的国家处于“过量”,而摄入较低的国家则处于“不足”。

至于第二主成分,其在鱼类、淀粉类食物以及果蔬上的取值为较高的负值。 这意味着各国的饮食在很大程度上受到地理位置的影响,例如沿海地区偏好鱼类,而内陆地区的饮食更富含蔬菜与土豆。

主成分的可视化 

前面对载荷矩阵的分析帮助我们理解了前两个主成分与数据属性之间的关系,但其可视化表现可能并不直观。 

有几种常见的可视化策略可以帮助用户从数据中获取洞见,本节将介绍其中一部分方法,先从碎石图开始。  

碎石图

首个方法是碎石图。它用于可视化各主成分的重要性,并可辅助确定保留的主成分个数。可通过 fviz_eig() 函数生成碎石图。 

fviz_eig(data.pca, addlabels = TRUE)

主成分的碎石图

主成分的碎石图

该图展示了特征值从高到低的下降曲线。前两个成分可视为最重要,因为它们几乎包含了数据总信息的 89%。

属性的双标图

通过双标图,可以同时可视化样本之间的相似与差异,并进一步展示各属性对各主成分的影响。

# 变量图
fviz_pca_var(data.pca, col.var = "black")

变量的双标图

相对于主成分的变量双标图

从上图可以观察到三点主要信息。 

  • 首先,聚在一起的变量彼此正相关,例如白肉/红肉、牛奶与鸡蛋两两正相关。这一结果并不意外,因为它们在第一主成分上的载荷值最高。
  • 其次,变量距离原点越远,说明该变量的表示越好。从双标图看,鸡蛋、牛奶与白肉的幅度高于红肉,因此相较红肉,它们的表示更好。
  • 最后,负相关的变量在双标图原点的两侧相对而立。 

各变量的贡献 

第三种可视化的目标是确定某个成分对每个变量的表示程度。这种表示质量称为 Cos2(平方余弦),可使用 fviz_cos2() 函数计算。

  • 低值意味着该变量并未被该成分很好地表示。 
  • 而高值则表示该变量在该成分上的表示较好。
fviz_cos2(data.pca, choice = "var", axes = 1:2)

上述代码计算了相对于前两个主成分的每个变量的平方余弦值。 

从下图可见,谷物、豆类坚果油籽、鸡蛋与牛奶是 cos2 最高的前四个变量,因此对 PC1 与 PC2 贡献最大。

变量对主成分的贡献

变量对主成分的贡献

结合 cos2 的双标图 

最后两种可视化——双标图与属性重要性——可以结合起来,生成单个双标图:cos2 得分相近的属性将呈现相近的颜色。这可以通过如下方式微调 fviz_pca_var 函数来实现:  

fviz_pca_var(data.pca, col.var = "cos2",
            gradient.cols = c("black", "orange", "green"),
            repel = TRUE)

从下方双标图可见:

  • 高 cos2 的属性为绿色:谷物、豆类、油籽、鸡蛋与牛奶。  
  • 中等 cos2 的属性为橙色:白肉、淀粉类食物、鱼和红肉。
  • 最后,低 cos2 的属性为黑色:水果和蔬菜, 

双标图与 cos2 得分的结合

双标图与 cos2 得分的结合

如何选择成分数量

两个实用准则可帮助决定保留多少个主成分:

  • 肘部法则:查看碎石图,找到曲线明显拐弯的位置。肘部右侧的成分对方差的新增贡献很小。
  • 方差阈值:保留足以解释 80% 至 90% 总方差的成分。在本数据集中,前两个成分已能解释约 89%。

 结语

本教程介绍了什么是主成分分析以及它在数据分析中的重要性。从数学基础到 R 代码实操,我们在蛋白质数据集上完整走了一遍 PCA 工作流——从规范化、应用 princomp(),到解读碎石图、双标图与 cos2 可视化,以理解主成分与原始变量之间的关系。

将这些技术应用到您自己的数据集,以实现降维、挖掘潜在结构,并构建更精炼的机器学习流水线。

想要进一步学习,请探索以下相关资源:

  • Python 中的主成分分析——将同样的技术应用到表格和图像数据集
  • 理解 UMAP——适用于复杂数据结构的非线性降维替代方案
  • 理解降维——包括 PCA、t-SNE 与 UMAP 在内的方法概览
  • 维度灾难——为何高维数据具有挑战性,以及 PCA 如何提供帮助
  • R 入门——通过动手练习夯实 R 基础

PCA 分析常见问答

PCA 属于特征提取还是特征选择?

PCA 通过无监督的线性变换实现特征提取与降维。

何时应使用 PCA 分析?

当变量之间强相关时,建议使用 PCA。若相关性较弱,PCA 可能难以更好地实现降维。

PCA 的局限性是什么?

首先,PCA 仅适用于数值型变量;其次,当变量之间不具备强相关性时,PCA 表现不佳。此外,PCA 对特征量纲敏感,且容易受到异常值影响。

PCA 的主要优势是什么?

PCA 的优势包括但不限于:

  • 通过移除噪声变量减少数据维度,从而也可能降低过拟合。
  • 聚焦相关特征以提升算法性能。
  • 改进数据可视化,便于更好理解数据。

主成分分析中的 PC1 与 PC2 是什么?

PC1 轴对应数据变化最大的一阶主方向。PC2 轴对应数据变化次大的第二主方向。此外,PC1 始终与 PC2 正交。

主成分分析有哪些假设?

主成分分析包含以下假设:

  • 变量之间可以进行线性组合。
  • 假设方差更高的主成分更重要,而方差较低者包含更多噪声。
  • 更多异常值通常意味着实验误差。
  • PCA 得到的数据表示可很好地表征原始数据。

如何在 R 中进行 PCA?

在 R 中执行 PCA,先用 scale() 规范化数据,然后使用 prcomp()(推荐——使用 SVD,数值更稳定)或基 R 的 princomp(),或 FactoMineR 包中的 PCA() 函数。使用 factoextra 包配合 fviz_eig() 生成碎石图,配合 fviz_pca_var() 生成双标图以可视化结果。

R 中 prcomp() 与 princomp() 有何区别?

prcomp() 使用奇异值分解(SVD),在数值上更稳定,通常更受青睐。princomp() 对协方差矩阵进行谱分解。对于条件良好的数据,两者结果等价,但大多数实际用例建议使用 prcomp()。主要输出差异在于:prcomp() 将载荷存于 $rotation,princomp() 则存于 $loadings。

PCA 能用于 R 中的机器学习预处理吗?

可以。PCA 常作为机器学习流水线中的预处理步骤,用于减少输入特征数量、去除预测变量间的多重共线性,并加速模型训练。在 R 中,可通过 prcomp() 的 $x 提取主成分得分,用作后续模型的输入特征。caret 与 tidymodels 都支持将 PCA 作为预处理步骤,分别对应 preProcess(method = "pca") 与 step_pca()。

我该如何选择要保留的主成分数量?

选择保留成分数量的三种常见方法:

  • 肘部法则:查看碎石图并找到拐点——拐点右侧的成分对方差的增量贡献逐渐变小。
  • 方差阈值:保留足以解释 80–90% 总方差的成分。
  • Kaiser 准则:保留特征值大于 1 的成分(更适用于较大的数据集)。

在 R 中,可使用 factoextra 包的 fviz_eig() 可视化各成分的方差解释率。

主题
R
数据分析

R 课程

课程

R 语言入门

4 小时
3.1M
掌握 R 数据分析基础,包括向量、列表和数据框,并用真实数据集实践 R。
查看详情Right Arrow
开始课程
查看更多Right Arrow