高效查找NumPy矩阵中的唯一列及其索引
高效查找NumPy矩阵中的唯一列及其索引
嗨,针对你遇到的这个超大二进制矩阵找唯一列+对应索引的内存高效方案问题,我来给你调整一下原有的行处理方法,完美适配到列的场景,同时还能拿到你需要的索引~
核心思路
原方法的核心是把矩阵行打包成结构化数组,利用np.unique的内存高效模式处理。我们只需要转置矩阵,把目标列转换成行,就能复用这套逻辑,处理完再转回来就行——全程用视图(view)操作,几乎不额外占用内存,完全符合你的内存优先需求。
完整代码示例
下面就用你给的测试矩阵来演示,最终能拿到唯一列和它们在原矩阵中首次出现的列索引:
import numpy as np # 测试用的二进制矩阵 data = np.array([[1, 1, 1, 0, 0, 0], [0, 1, 1, 1, 0, 0], [0, 1, 1, 1, 0, 0], [1, 1, 1, 0, 0, 0], [1, 1, 1, 1, 1, 0]], dtype=np.byte) # 1. 转置矩阵:把原矩阵的列转换成行,方便复用行处理逻辑 transposed_data = data.T # 2. 构造结构化数组的dtype:把每个元素的类型描述重复原矩阵的行数(转置后的列数)次 n_rows_original = data.shape[0] dtype = data.dtype.descr * n_rows_original # 3. 将转置后的矩阵转为结构化数组(视图操作,无内存复制) struct_arr = transposed_data.view(dtype) # 4. 用np.unique处理,拿到唯一结构化数组和它们的首次出现索引(对应原矩阵的列索引) unique_struct, unique_col_indices = np.unique(struct_arr, return_index=True) # 5. 把唯一结构化数组转回原矩阵的列格式,再转置得到最终的唯一列 unique_columns = unique_struct.view(data.dtype).reshape(-1, n_rows_original).T # 输出结果看看 print("原矩阵的唯一列:") print(unique_columns) print("\n唯一列在原矩阵中首次出现的列索引:") print(unique_col_indices)
运行这段代码后,你会得到:
unique_columns:原矩阵中所有不重复的列unique_col_indices:每个唯一列在原矩阵里第一次出现的列位置索引
扩展:获取每个唯一列的所有出现索引
如果你不仅需要首次出现的索引,还想知道每个唯一列在原矩阵中所有的列位置,可以稍微调整一下,用return_inverse=True来收集所有对应关系:
import numpy as np from collections import defaultdict data = np.array([[1, 1, 1, 0, 0, 0], [0, 1, 1, 1, 0, 0], [0, 1, 1, 1, 0, 0], [1, 1, 1, 0, 0, 0], [1, 1, 1, 1, 1, 0]], dtype=np.byte) transposed_data = data.T n_rows_original = data.shape[0] dtype = data.dtype.descr * n_rows_original struct_arr = transposed_data.view(dtype) # 用return_inverse拿到原数组每个元素对应的唯一数组索引 unique_struct, inverse_indices = np.unique(struct_arr, return_inverse=True) unique_columns = unique_struct.view(data.dtype).reshape(-1, n_rows_original).T # 收集每个唯一列对应的所有原列索引 col_indices_map = defaultdict(list) for original_col_idx, unique_idx in enumerate(inverse_indices): col_indices_map[unique_idx].append(original_col_idx) # 输出每个唯一列的所有原列索引 for unique_idx, original_cols in col_indices_map.items(): print(f"唯一列{unique_idx}对应的原矩阵列索引:{original_cols}")
这个方案依然保持了内存高效的特点,因为全程没有大的内存复制操作,只是通过视图和字典做了索引映射。
备注:内容来源于stack exchange,提问作者farid_musa
相关产品推荐
相关产品推荐

