如何在3D图中添加PCA第一主成分可视化直线?
解决方案
你的3D图目前要么用的是原始特征而非PCA降维结果,要么缺少第一主成分直线的坐标计算逻辑。以下分两种常见场景给出修改方案:
场景1:在PCA降维后的3D空间展示第一主成分直线
这是PCA可视化的常规做法,降维后第一主成分对应PC1轴,直线沿该轴延伸。
修改后的完整代码:
import numpy as np np.set_printoptions (suppress=True, precision=5, linewidth=150) import pandas as pd from sklearn.decomposition import PCA from sklearn.preprocessing import LabelEncoder from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt file_name = 'C:/Users/data' input_data = pd.read_csv (file_name + '.csv', header=0, index_col=0) A = input_data.A.values.astype(float) B = input_data.B.values.astype(float) C = input_data.C.values.astype(float) D = input_data.D.values.astype(float) E = input_data.E.values.astype(float) F = input_data.F.values.astype(float) X = np.column_stack((A, B, C, D, E, F)) ncompo = int (input ("Number of components to study: ")) print("") pca = PCA (n_components = ncompo) pcafit = pca.fit(X) X_pca = pca.transform(X) # 获取PCA降维后的数据 perc = pcafit.explained_variance_ratio_ perc_x = range(1, len(perc)+1) plt.plot(perc_x, perc) plt.xlabel('Components') plt.ylabel('Percentage of Variance Explained') plt.show() # 3D可视化:PCA降维后的空间 plt.clf() le = LabelEncoder() le.fit(input_data.Grade) number = le.transform(input_data.Grade) colormap = np.array(['green', 'blue', 'red', 'yellow']) fig = plt.figure() ax = fig.add_subplot(111, projection='3d') # 用PCA前3个主成分绘制散点 ax.scatter(X_pca[:,0], X_pca[:,1], X_pca[:,2], c=colormap[number]) # 绘制第一主成分直线 min_pc1 = X_pca[:,0].min() max_pc1 = X_pca[:,0].max() line_x = np.linspace(min_pc1, max_pc1, 100) line_y = np.zeros_like(line_x) line_z = np.zeros_like(line_x) ax.plot(line_x, line_y, line_z, color='black', linewidth=2, label='First Principal Component') ax.set_xlabel('PC1') ax.set_ylabel('PC2') ax.set_zlabel('PC3') ax.legend() plt.title('PCA 3D Visualization') plt.show()
关键修改点:
- 新增
X_pca = pca.transform(X)获取降维后的数据 - 散点图改用PCA前3个主成分,而非原始特征
- 第一主成分在PCA空间中对应x轴,生成y/z为0的直线,覆盖PC1的全数据范围
场景2:在原始D/E/F特征的3D空间展示全局第一主成分直线
如果需要在原始D-E-F三维空间中展示6维数据的第一主成分方向,需基于原始数据均值和主成分向量生成直线:
修改3D图部分的代码如下:
# 3D可视化:原始D/E/F空间 + 第一主成分直线 plt.clf() le = LabelEncoder() le.fit(input_data.Grade) number = le.transform(input_data.Grade) colormap = np.array(['green', 'blue', 'red', 'yellow']) fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.scatter(D, E, F, c=colormap[number]) # 生成第一主成分直线 mean_X = X.mean(axis=0) # 原始6维数据的均值 pc1 = pca.components_[0] # 第一主成分的方向向量(已按方差排序) scale = 3 * np.sqrt(pca.explained_variance_[0]) # 3倍标准差,确保直线覆盖大部分数据 line_points = mean_X + np.linspace(-scale, scale, 100)[:, np.newaxis] * pc1 # 提取D/E/F对应的分量(X中第3、4、5列) line_D = line_points[:, 3] line_E = line_points[:, 4] line_F = line_points[:, 5] ax.plot(line_D, line_E, line_F, color='black', linewidth=2, label='First Principal Component') ax.set_xlabel('D') ax.set_ylabel('E') ax.set_zlabel('F') ax.legend() plt.title('PCA') plt.show()
关键说明:
pca.components_[0]是sklearn PCA输出的第一主成分方向向量,已按方差从大到小排序- 以原始数据均值为直线中点,通过缩放因子控制直线延伸范围,匹配数据分布
- 从6维直线点中提取D/E/F分量,与你的3D图坐标轴对应
内容的提问来源于stack exchange,提问作者T.Lyons
相关产品推荐
相关产品推荐

