如何用NumPy/SciPy映射数组值消除间隙并随机重排?
嘿,这两个需求都能用NumPy完美解决,我来给你一步步拆解:
1. 生成无值间隙且保持原顺序的映射数组
你的核心需求是:把原数组中每个不同元素映射到连续的整数(从0开始,无缺失),相同元素对应同一个值,同时完全保留原数组的元素顺序。
用NumPy的np.unique()函数就能直接搞定,关键是用到它的return_inverse参数——这个参数会返回原数组每个元素在排序后的唯一元素数组中的索引,刚好匹配你给出的示例输出:
import numpy as np a = np.array([0,0,1,1,4,4,4,4,5,1891,7]) # 获取排序后的唯一元素,以及原元素对应的映射索引 _, arr_map = np.unique(a, return_inverse=True) print(arr_map) # 输出: [0 0 1 1 2 2 2 2 3 5 4]
如果你的需求是按元素首次出现的顺序分配映射值(而非按数值大小排序),可以稍微调整逻辑,用return_index参数先锁定首次出现的位置,再生成映射:
# 获取每个唯一元素首次出现的索引 _, idx = np.unique(a, return_index=True) # 按首次出现顺序排序得到唯一元素列表 unique_ordered = a[np.sort(idx)] # 生成每个元素对应的映射值 arr_map = np.searchsorted(unique_ordered, a) print(arr_map) # 输出: [0 0 1 1 2 2 2 2 3 4 5]
这个版本里,1891会被映射为4,7映射为5,因为它们首次出现的顺序在5之后。
2. 打乱映射后的数值
要交换/打乱映射后的数值,本质就是定义一个置换规则,用置换数组重新映射原结果即可。
比如你想要把示例中的[0,0,1,1,2,2,2,2,3,5,4]转换成[0,0,3,3,5,5,5,5,4,1,2],可以先自定义置换规则,再应用到原映射结果上:
# 原映射结果 arr_map = np.array([0,0,1,1,2,2,2,2,3,5,4]) # 置换数组:索引是原映射值,对应的值是新的映射值 perm = np.array([0, 3, 5, 4, 2, 1]) # 应用置换规则 shuffled_arr = perm[arr_map] print(shuffled_arr) # 输出: [0 0 3 3 5 5 5 5 4 1 2]
如果想要随机打乱映射值(保证每个原映射值对应唯一的新值,无冲突),可以用np.random.permutation()生成随机置换:
# 获取映射值的范围(0到最大映射值) n = arr_map.max() + 1 # 生成随机置换数组 random_perm = np.random.permutation(n) # 应用随机置换 random_shuffled = random_perm[arr_map] print(random_shuffled) # 输出类似: [1 1 0 0 3 3 3 3 4 2 5](每次运行结果不同)
内容的提问来源于stack exchange,提问作者Liwellyen
相关产品推荐
相关产品推荐

