解决numpy数组互换两行及赋值的问题
本文探讨在Python中使用numpy交换数组两行时,直接赋值导致的引用共享问题。通过示例展示错误现象,并给出使用切片索引或np.copy()深度拷贝两种正确实现方式,帮助开发者避免数据覆盖错误。
首先来看一段代码示例。
import numpy as np
a = np.array([[1,1,1],[2,2,2],[3,3,3], [4,4,4]])
tmp = a[1]
a[1] = a[2]
a[2] = tmp
这里的tmp变量实际上只是数组a中第2行(索引为1)的一个引用别名,并非该行的独立副本。因此,这段代码无法实现预期的第2行与第3行互换,反而会导致第2行和第3行都变成原第3行的数据[3,3,3],具体表现如下:
array([[1, 1, 1],
[3, 3, 3],
[3, 3, 3],
[4, 4, 4]])
那么,如何正确地交换数组的两行呢?
这里提供两种方法,第一种非常简洁:
a[[1,2], :] = a[[2,1], :]
执行上述代码后,数组a的第2行和第3行便成功互换。或者,为了逻辑更清晰,也可以分步书写:
tmp = np.copy(a[1])
a[1] = a[2]
a[2] = tmp
这两种写法均能实现数组a第2、3行的互换,最终结果如下:
array([[1, 1, 1],
[3, 3, 3],
[2, 2, 2],
[4, 4, 4]])
补充说明:关于numpy数组行交换的一个常见陷阱。
今天发现了一个小问题,幸好及时察觉,否则这个bug可能会带来长期的困扰。
实验目标设定为:
交换numpy数组中的第i行与第j行。
具体代码如下:
import numpy as np
arr = np.asarray([[1,2,3], [4,5,6], [7,8,9]])
print(arr)
tmp = arr[2]
arr[2] = arr[0]
arr[0] = tmp
print(arr)
运行打印结果如下:
[[1 2 3]
[4 5 6]
[7 8 9]]
[[1 2 3]
[4 5 6]
[1 2 3]]
看到这样的输出结果,确实令人困惑。
为了弄清楚原因,我打印了中间变量tmp的值。
import numpy as np
arr = np.asarray([[1,2,3], [4,5,6], [7,8,9]])
print(arr)
tmp = arr[2]
print(tmp)
arr[2] = arr[0]
print(tmp)
arr[0] = tmp
print(arr)
打印结果如下:
[[1 2 3]
[4 5 6]
[7 8 9]] #原始的arr
[7 8 9] #第一次打印tmp
[1 2 3] #第二次打印tmp
[[1 2 3]
[4 5 6]
[1 2 3]] #交换后的arr
问题根源在于Python的特性:变量tmp并没有复制arr[2]的数值,而是像C语言中的指针一样指向了arr[2]的内存地址。当执行arr[2] = arr[0]后,arr[2]的数据发生变化,tmp所指向的内容也随之改变。
解决方法很简单,对变量tmp进行arr[2]的深度拷贝即可,即使用代码:tmp = arr[2].copy()。
import numpy as np
arr = np.asarray([[1,2,3], [4,5,6], [7,8,9]])
print(arr)
tmp = arr[2].copy()
print(tmp)
arr[2] = arr[0]
print(tmp)
arr[0] = tmp
print(arr)
再次打印结果:
[[1 2 3]
[4 5 6]
[7 8 9]] #原始的arr
[7 8 9] #第一次打印tmp
[7 8 9] #第二次打印tmp
[[7 8 9]
[4 5 6]
[1 2 3]] #交换后的arr
问题得以解决。
以上为个人经验分享,希望能提供参考。欢迎大家多多支持本站。如有错误或未考虑周全之处,敬请指正。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













