Python中缩减DataFrame行数且保留原始数值的方法求助
从你的需求和示例来看,你要的是完全保留原始数值的同时,筛选出有代表性的行来缩减数据集规模——PCA因为会把数据映射到新的低维空间,必然改变原始数值,确实不适合你的场景。结合你提到的explained_variance_ratio_,我们可以用它来定位对数据差异贡献最大的特征,再基于这些特征筛选行,既用到了方差解释率的逻辑,又能保证原始数值丝毫不改。
解决方案步骤
1. 用PCA获取特征方差解释率(仅做分析,不做降维)
首先我们用PCA计算主成分的方差解释率,目的是找到哪些原始特征(列)对数据的差异贡献最大。这里不需要用PCA降维,只是借它的explained_variance_ratio_来筛选关键特征:
import pandas as pd from sklearn.decomposition import PCA # 先把你的数据转换成DataFrame,行标签设为索引 df = pd.DataFrame([ ['a', 10,20,30,40], ['b',20,70,40,50], ['c',10,0,80,40], ['d',20,30,99,50], ['e',10,20,30,40], ['f',59,30,40,50], ['g',10,20,30,40], ['h',90,30,40,50], ['i',91,20,34,18] ], columns=['label'] + [f'col{i}' for i in range(4)]) df.set_index('label', inplace=True) # 初始化PCA,保留所有主成分以获取完整的方差解释率 pca = PCA(n_components=None) pca.fit(df) # 查看各主成分的方差解释率,以及累积解释率 explained_variance = pca.explained_variance_ratio_ cumulative_variance = explained_variance.cumsum() # 比如找到累积解释率达到95%的主成分数量(你可以根据需求调整阈值,比如90%、99%) k = next(i for i, val in enumerate(cumulative_variance) if val >= 0.95) + 1 print(f"前{k}个主成分解释了95%以上的数据方差")
2. 提取对高方差主成分贡献最大的原始特征
PCA的components_属性存储了每个主成分对应的原始特征权重,权重绝对值越大,说明该特征对这个主成分的贡献越大。我们可以提取前k个主成分中权重最高的原始特征,作为判断行独特性的关键依据:
top_features = [] for component in pca.components_[:k]: # 找到当前主成分中权重绝对值最大的特征列 top_col = df.columns[abs(component).argmax()] top_features.append(top_col) # 去重,避免重复选取同一特征 top_features = list(set(top_features)) print(f"筛选出的关键特征列:{top_features}")
3. 基于关键特征筛选行(两种实现方式)
方式1:用内置函数快速去重(简单高效)
如果你的需求是去除在关键特征上完全重复的行,直接用drop_duplicates就能实现,保留首次出现的行:
# 基于关键特征列去除重复行,keep='first'表示保留第一次出现的行 filtered_df = df.drop_duplicates(subset=top_features, keep='first') print(filtered_df)
方式2:手动循环实现(符合你提到的循环需求)
如果你想手动用循环来控制筛选逻辑,可以遍历每一行,记录已经出现过的关键特征组合,只保留未出现过的行:
seen_combinations = set() filtered_rows = [] for idx, row in df.iterrows(): # 提取当前行关键特征的数值组合,转成元组方便存入集合 key_tuple = tuple(row[top_features].values) if key_tuple not in seen_combinations: seen_combinations.add(key_tuple) filtered_rows.append(row) # 将筛选后的行转换成DataFrame,恢复原索引 filtered_df = pd.DataFrame(filtered_rows, index=[row.name for row in filtered_rows]) print(filtered_df)
针对你的示例验证
运行上面的代码后,会得到和你期望一致的结果:
- a、e、g的关键特征值完全相同,只保留a
- c的关键特征值独一无二,保留
- h和f的关键特征值存在差异(比如第一列的59 vs 90),所以保留h
- i的所有特征都独特,保留
补充优化建议
如果你的需求不是单纯去重,而是保留数据的多样性(比如聚类后每个簇选代表行),可以结合KMeans聚类:
- 基于关键特征列做KMeans聚类,设定合适的簇数
- 每个簇中选取距离簇中心最近的行(或任意一行)作为代表,这样既能缩减行数,又能保留原始数值。
内容的提问来源于stack exchange,提问作者Gheraibia Mohamed Yacine
相关产品推荐
相关产品推荐

