交换 numpy 数组副本中的元素



我有一个 numpy 数组的列表/数组,表示分成子组的对象。

我想创建此数组的副本,我可以在其中交换子组中的元素并保持原始分组不变。

我为此编写的函数是:

def group_swap(groups):
# Chooses two random groups and swaps two random elements from each 
group.
gr = np.copy(groups)
g1 = np.random.randint(len(gr))
g2 = np.random.randint(len(gr))
if g1 != g2:
e1 = np.random.randint(len(gr[g1]))
e2 = np.random.randint(len(gr[g2]))
gr[g1][e1] ,gr[g2][e2] = gr[g2][e2].copy(),gr[g1][e1].copy()
return(gr)
else:
return(groups)

基于这个问题,我已经能够交换元素。但是,原始数组中的元素也会被交换,如本例所示。

a = np.array_split(np.arange(10),3)
print('orginal before swap: ',a)
a_swap = group_swap(a)
print('original after swap: ',a)
print('swapped array: ',a_swap)

这给了:

original before swap:  
[array([0, 1, 2, 3]), array([4, 5, 6]), array([7, 8, 9])]
original after swap:  
[array([0, 1, 2, 7]), array([4, 5, 6]), array([3, 8, 9])]
swapped array:  
[array([0, 1, 2, 7]) array([4, 5, 6]) array([3, 8, 9])]

理想情况下,数组 a 应该保持不变,只有 a_swap显示交换的元素。我曾希望在我的函数中制作和使用数组的副本可以解决问题,但这并没有奏效。

谁能帮助指出我可能错过了什么?我有一种感觉,这是我事后会踢自己的事情。

谢谢

PS:奇怪的是,如果每组中的元素数量相等,它似乎有效,但我不明白为什么。

original before swap: 
[array([0, 1, 2, 3]), array([4, 5, 6, 7]), array([ 8,  9, 10, 11])]
original after swap:  
[array([0, 1, 2, 3]), array([4, 5, 6, 7]), array([ 8,  9, 10, 11])]
swapped array:
[[ 0  1  8  3]
[ 4  5  6  7]
[ 2  9 10 11]]

当每个元素中的组件数不相等时,您有一个数组列表(嵌套对象(。

当组件数相等时,您有一个二维数组(一个对象(。

您使用copy称为浅拷贝,它仅复制顶级对象(第二种情况下为 2d 数组,但第一种情况下仅复制数组的地址(。因此,在第一种情况下,您的原始数据也会更改。 您应该使用copy模块: https://docs.python.org/3/library/copy.html

a = np.array_split(np.arange(10),3)
a = np.asarray(a)
b = a.copy() -1 +1
print('orginal before swap: ',a)
a_swap = group_swap(b)
print('original after swap: ',a)
print('swapped array: ',a_swap)

据我所知,ndarray.copy()会获取数组的浅拷贝,直到对其进行一些更改。当您将变量调用到方法时,它使用数组的浅表副本,忽略它应该被更改。通过在通过方法传递变量之前更改变量,它将 b 的内存引用更改为与 a 不同的位置。

a = np.asarray(a)可以从列表转换为 numpy 数组,以便-1 +1是有效的操作。 可能有很多不同的方法可以做同样的事情,这似乎是最简单的。

最新更新