You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何提取y=0对应PCA特征的两个命令返回不同结果?

问题描述

我有一个形状为(2250,2)的NumPy数组x_pcaed,以及一个包含2250行的Pandas DataFrameseeds_train,其中包含一列值为0或1的y列。

我执行了以下操作:

  • 将x_pcaed转换为DataFrame:
    pca_df = pd.DataFrame(data = x_pcaed, columns=['pr_comp_1', 'pr_comp_2'])
    
  • 拼接生成新的DataFrame:
    test1 = pd.concat([pca_df, seeds_train[['y']]], axis=1)
    

但以下两个命令返回的结果不一致,我认为它们应该输出相同结果,肯定遗漏了某些细节:

  1. 命令1:
    test1.loc[test1['y']==0,'pr_comp_1'].values
    
  2. 命令2:
    x_pcaed[seeds_train.y==0, 0]
    

完整代码

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler

seeds = pd.read_excel('Pumpkin_Seeds_Dataset.xlsx')
seeds['y'] = 0
seeds.loc[seeds.Class=='Ürgüp Sivrisi', 'y']=1

seeds_train, seeds_test = train_test_split(seeds.copy(),
                                              shuffle=True,
                                              random_state=123,
                                              test_size=.1,
                                              stratify=seeds.y.values)

features = seeds_train.columns[:-2]
x = seeds_train.loc[:,features].values
scaler = StandardScaler()
x_scaled = scaler.fit_transform(x)
pca = PCA(n_components = 2)
x_pcaed = pca.fit_transform(x_scaled)
pca_df = pd.DataFrame(data = x_pcaed, columns=['pr_comp_1', 'pr_comp_2'])
test1 = pd.concat([pca_df, seeds_train[['y']]], axis=1)

print(test1.loc[test1['y']==0,'pr_comp_1'].values)
print('----------')
print(x_pcaed[seeds_train.y==0, 0])

输出结果

[-0.79984874 -2.75176272 -0.26329661 ... -2.03461928 -2.38149466
 -1.46663563]
----------
[-1.36392527 -0.26329661 -4.91873745 ... -1.46508442 -1.07096868
 -4.79462993]

问题原因

核心问题是索引不匹配:

  • train_test_split开启shuffle=True后,seeds_train的索引会被打乱(不再是从0开始的连续整数)。
  • 创建pca_df时,Pandas会自动生成从0开始的连续默认索引。
  • 使用pd.concat拼接时,是按照索引对齐来合并数据的,这就导致pca_df里的PCA结果和seeds_train里的y值对应关系错乱了——pca_df的第i行对应原数据的第i行,但seeds_train的第i行(按索引)已经是洗牌后的另一行数据。

而x_pcaed[seeds_train.y==0, 0]是直接用seeds_train的布尔索引提取x_pcaed的行,这里x_pcaed的行顺序和seeds_train的行顺序完全一致(因为x是从seeds_train提取的,后续标准化、PCA都是按原顺序处理),所以这个结果是正确的。


解决方法

有两种可行的修正方式:

方法1:统一索引,确保拼接时行对应

可以在创建pca_df时指定其索引与seeds_train一致,或者重置seeds_train的索引:

# 方式1:创建pca_df时指定索引
pca_df = pd.DataFrame(data = x_pcaed, columns=['pr_comp_1', 'pr_comp_2'], index=seeds_train.index)
test1 = pd.concat([pca_df, seeds_train[['y']]], axis=1)

# 方式2:重置seeds_train的索引(丢弃原索引)
seeds_train = seeds_train.reset_index(drop=True)
pca_df = pd.DataFrame(data = x_pcaed, columns=['pr_comp_1', 'pr_comp_2'])
test1 = pd.concat([pca_df, seeds_train[['y']]], axis=1)

方法2:用原DataFrame的布尔索引提取

如果不想修改索引,直接用seeds_train的布尔索引去取test1的对应行,就能得到和x_pcaed[seeds_train.y==0, 0]一致的结果:

test1.loc[seeds_train.y==0, 'pr_comp_1'].values

内容的提问来源于stack exchange,提问作者user21222252

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 09:30:58