Python 中 PCA 图中的项目变量

Project variables in PCA plot in Python

在 R 中执行 PCA 分析后,我们可以:

ggbiplot(pca, choices=1:2, groups=factor(row.names(df_t)))

这将绘制 2 PC space 中的数据,以及 space 中变量的方向和权重作为向量(具有不同的长度和方向)。

在Python中我可以画出2台PC中的数据space,我可以得到变量的权重,但是我怎么知道方向呢

换句话说,我如何在 Python 中绘制对 PC(权重和方向)的变量贡献?

我不知道这种情节有任何预制实现,但可以使用 matplotlib.pyplot.quiver 创建。这是我快速组合的示例。您可以以此为基础创建适合您的数据的精美图表。


示例数据

这会生成一些示例数据。它从 .

中重复使用
# User input
n_samples  = 100
n_features =   5

# Prep
data  = np.empty((n_samples,n_features))
np.random.seed(42)

# Generate
for i,mu in enumerate(np.random.choice([0,1,2,3], n_samples, replace=True)):
    data[i,:] = np.random.normal(loc=mu, scale=1.5, size=n_features)

PCA

pca = PCA().fit(data)

变量因子图

我们开始:

# Get the PCA components (loadings)
PCs = pca.components_

# Use quiver to generate the basic plot
fig = plt.figure(figsize=(5,5))
plt.quiver(np.zeros(PCs.shape[1]), np.zeros(PCs.shape[1]),
           PCs[0,:], PCs[1,:], 
           angles='xy', scale_units='xy', scale=1)

# Add labels based on feature names (here just numbers)
feature_names = np.arange(PCs.shape[1])
for i,j,z in zip(PCs[1,:]+0.02, PCs[0,:]+0.02, feature_names):
    plt.text(j, i, z, ha='center', va='center')

# Add unit circle
circle = plt.Circle((0,0), 1, facecolor='none', edgecolor='b')
plt.gca().add_artist(circle)

# Ensure correct aspect ratio and axis limits
plt.axis('equal')
plt.xlim([-1.0,1.0])
plt.ylim([-1.0,1.0])

# Label axes
plt.xlabel('PC 0')
plt.ylabel('PC 1')

# Done
plt.show()


不确定

我对箭头的缩放有点费劲。请确保它们正确反映了您数据的负载。快速检查 feature 4 是否真的与 PC 1 密切相关(如本例所示)看起来很有希望:

data_pca = pca.transform(data)
plt.scatter(data_pca[:,1], data[:,4])
plt.xlabel('PC 2') and plt.ylabel('feature 4')
plt.show()

感谢 WhoIsJack 早前的回答。

我将那里的代码改编为下面的一个函数,该函数接受一个合适的 PCA 对象及其所基于的数据。它生成与上图类似的图,但我用实际的列名替换了列索引,然后将其修剪为仅显示一定数量的贡献列。

def plot_pca_vis(pca, df: pd.DataFrame, pc_x: int = 0, pc_y: int = 1, num_dims: int = 5):
    """
    
    Adapted into function by Tim Cashion
    """
    # Get the PCA components (loadings)
    PCs = pca.components_

    PC_x_index = PCs[pc_x, : ].argsort()[-num_dims:][::-1]
    PC_y_index = PCs[pc_y, : ].argsort()[-num_dims:][::-1]
    combined_index = set(list(PC_x_index) + list(PC_y_index))
    PCs = PCs[:, list(combined_index)]
    # Use quiver to generate the basic plot
    fig = plt.figure(figsize=(5,5))
    plt.quiver(np.zeros(PCs.shape[1]), np.zeros(PCs.shape[1]),
            PCs[pc_x,:], PCs[pc_y,:], 
            angles='xy', scale_units='xy', scale=1)

    # Add labels based on feature names (here just numbers)
    feature_names = df.columns
    for i,j,z in zip(PCs[pc_y,:]+0.02, PCs[pc_x,:]+0.02, feature_names):
        plt.text(j, i, z, ha='center', va='center')

    # Add unit circle
    circle = plt.Circle((0,0), 1, facecolor='none', edgecolor='b')
    plt.gca().add_artist(circle)

    # Ensure correct aspect ratio and axis limits
    plt.axis('equal')
    plt.xlim([-1.0,1.0])
    plt.ylim([-1.0,1.0])

    # Label axes
    plt.xlabel('PC ' + str(pc_x))
    plt.ylabel('PC ' + str(pc_y))
    # Done
    plt.show()              

希望这对某人有所帮助!