Numpy数组批量打乱时索引赋值异常原因咨询
为什么NumPy中
row[idx] = row赋值会出现重复值? 你尝试将向量重塑为二维数组后逐行打乱,但使用row[idx] = row时出现了重复值,换成row[:] = row[idx]就正常工作,核心原因是NumPy原地赋值的执行顺序问题:
问题根源:原地赋值的顺序干扰
当执行row[idx] = row时,NumPy会按idx指定的位置依次进行赋值操作,而且是直接在原数组上修改。这意味着前面的赋值会覆盖row中的元素,后面的赋值操作再读取row的值时,已经是被修改过的版本,最终导致重复值出现。
举个具体例子:假设原row = [0,1,2,3],随机生成的idx = [2,0,1,3],执行row[idx] = row的过程是:
- 给
row[2]赋值row[0]→row变为[0,1,0,3] - 给
row[0]赋值row[1]→row变为[1,1,0,3] - 给
row[1]赋值row[2](此时row[2]已经是0)→row变为[1,0,0,3] - 给
row[3]赋值row[3]→row保持[1,0,0,3]
可以看到,中间步骤的修改导致后续读取的是被污染的值,最终出现重复的0,完全不是原行的打乱结果。
正确写法的原理:先计算完整结果再赋值
而row[:] = row[idx]的逻辑是:
- 先计算
row[idx],这会基于原始的row数组生成一个新的打乱后的数组(比如上面的例子会得到[2,0,1,3]) - 再将这个完整的新数组一次性赋值给
row[:](即覆盖原数组的所有元素)
这种方式避免了中间修改对后续赋值的干扰,因为右侧的row[idx]是在赋值前就计算完成的,使用的是row的原始值,最终得到的就是正确的逐行打乱结果。
额外补充
NumPy的索引赋值默认是按位置顺序执行原地修改,如果要避免这种干扰,要么像你那样先获取完整的打乱结果再赋值,要么可以使用np.random.shuffle(row)直接对行进行原地打乱,代码会更简洁:
for row in tmp_mat: np.random.shuffle(row)
内容的提问来源于stack exchange,提问作者Eric Johnson
相关产品推荐
相关产品推荐

