如何用Numpy高效实现按ID将行转列(含列数限制与补零)
用NumPy原生功能高效实现映射数组的重排需求
当然有!用Python循环处理确实不够高效,尤其是当数据量很大的时候,NumPy的矢量化操作能帮你把速度提上去一大截。下面我就给你演示怎么用纯NumPy原生函数实现你要的效果:
首先,先把你的示例数据准备好:
import numpy as np # 原映射数组 arr = np.array([[1, 12], [1, 13], [1, 14], [2, 13], [2, 14], [3, 11]]) # 指定列数限制 max_cols = 2
接下来分步骤操作:
拆分ID和对应值
把原数组拆分成ID列和对应的物品值列:ids, values = arr[:, 0], arr[:, 1]获取唯一ID及分组索引
用np.unique拿到所有不重复的ID,同时得到每个元素所属的组索引:unique_ids, group_idx = np.unique(ids, return_inverse=True)统计每个ID的元素数量
用np.bincount快速统计每个分组里有多少个元素:group_counts = np.bincount(group_idx)初始化结果数组
创建一个全0的结果数组,行数是唯一ID的数量,列数是你指定的限制:result = np.zeros((len(unique_ids), max_cols), dtype=values.dtype)生成组内元素的位置索引
给每个元素标记它在自己组内的位置(比如第1个、第2个...):group_pos = np.concatenate([np.arange(count) for count in group_counts])筛选并填充有效元素
只保留每个组内前max_cols个元素,然后用NumPy的高级索引把这些值填充到结果数组里:# 筛选出组内位置不超过列数限制的元素 valid_mask = group_pos < max_cols # 填充到对应位置 result[group_idx[valid_mask], group_pos[valid_mask]] = values[valid_mask]
最后运行代码,你就能得到想要的结果:
print(result) # 输出: # [[12 13] # [13 14] # [11 0]]
这种方法全程用NumPy的矢量化操作,没有Python层面的循环,处理大规模数据时效率会比循环高很多。而且逻辑清晰,完全符合你的需求:超出列数的元素被截断,不足的用0补位。
内容的提问来源于stack exchange,提问作者osm
相关产品推荐
相关产品推荐

