
本文介绍一种纯 NumPy 向量化方法,无需 Python 循环,即可根据标签数组 y 将数据数组 x 拆分为多个子数组,每个子数组对应 y 中一个唯一类别的所有样本。
本文介绍一种纯 numpy 向量化方法,无需 python 循环,即可根据标签数组 `y` 将数据数组 `x` 拆分为多个子数组,每个子数组对应 `y` 中一个唯一类别的所有样本。
在机器学习预处理、数据分组分析或批量特征提取等场景中,常需将特征矩阵 x(形状为 (n_samples, n_features))按对应的标签向量 y(长度为 n_samples)进行分组拆分。例如:
import numpy as np
x = np.array([[2,3,5,6],
[1,2,4,3],
[1,5,6,4],
[2,8,9,5]])
y = np.array([1,0,1,2])目标是得到按 y 值分组的字典:{0: x[y==0], 1: x[y==1], 2: x[y==2]},即:
- x_0 = [[1,2,4,3]](y == 0 的唯一一行)
- x_1 = [[2,3,5,6], [1,5,6,4]](y == 1 的两行)
- x_2 = [[2,8,9,5]](y == 2 的一行)
✅ 推荐方案:纯 NumPy 向量化三步法(高效、内存友好、无显式循环)
# 步骤 1:获取 y 的唯一值及其频次 unique_labels, counts = np.unique(y, return_counts=True) # 步骤 2:对 x 按 y 排序(保持一一对应),并计算累计分割点 sorted_x = x[np.argsort(y)] # 按 y 升序重排 x split_indices = np.cumsum(counts[:-1]) # 如 [1, 3] 表示在索引 1 和 3 处切分 # 步骤 3:一次性切分,并与标签配对生成字典 grouped_dict = dict(zip(unique_labels, np.array_split(sorted_x, split_indices))) print(grouped_dict)
输出:
功能列表:底层程序与前台页面分离的效果,对页面的修改无需改动任何程序代码。完善的标签系统,支持自定义标签,公用标签,快捷标签,动态标签,静态标签等等,支持标签内的vbs语法,原则上运用这些标签可以制作出任何想要的页面效果。兼容原来的栏目系统,可以很方便的插入一个栏目或者一个栏目组到页面的任何位置。底层模版解析程序具有非常高的效率,稳定性和容错性,即使模版中有错误的标签也不会影响页面的显示。所有的标
{
0: array([[1, 2, 4, 3]]),
1: array([[2, 3, 5, 6],
[1, 5, 6, 4]]),
2: array([[2, 8, 9, 5]])
}? 原理简析:
- np.argsort(y) 返回 y 元素升序排列的原始索引,用它索引 x 可使 x 行与 y 值严格对齐;
- np.cumsum(counts[:-1]) 生成分割点(如 counts=[1,2,1] → [1,3]),np.array_split(..., [1,3]) 将排序后数组切成 [0:1], [1:3], [3:] 三段;
- zip(unique_labels, ...) 精准绑定每个分组与其对应的标签。
⚠️ 注意事项:
- 该方法要求 len(x) == len(y),否则会触发索引错误;
- np.array_split 在分割点超出数组长度时仍能安全处理(返回空数组),但语义上建议确保 sum(counts) == len(y);
- 若需保持原始 y 中首次出现顺序(而非升序),可改用 np.unique(y, return_index=True) 并自定义排序键,但通常升序已满足多数需求;
- 对于超大规模数据,此方案比布尔索引(如 [x[y==k] for k in unique_labels])更省内存——后者需多次遍历 y 并生成中间布尔数组。
? 进阶提示:若后续需对各组执行相同操作(如归一化、统计),可直接遍历字典:
for label, group_x in grouped_dict.items():
print(f"Label {label}: mean = {group_x.mean(axis=0)}")该方法兼顾简洁性、性能与可读性,是 NumPy 生态中分组拆分任务的标准实践之一。









