我喜欢python处理变量交换的方式:
a, b, = b, a
我想使用此功能在数组之间交换值,不仅一次一个,而且还有一些(不使用临时变量)。这不是我的预期(我希望沿着第三维的两个条目都会交换两者):
import numpy as np
a = np.random.randint(0, 10, (2, 3,3))
b = np.random.randint(0, 10, (2, 5,5))
# display before
a[:,0, 0]
b[:,0,0]
a[:,0,0], b[:, 0, 0] = b[:, 0, 0], a[:,0,0] #swap
# display after
a[:,0, 0]
b[:,0,0]
有没有人有想法?当然我总是可以引入一个额外的变量,但我想知道是否有更优雅的方式来做这个。
答案 0 :(得分:20)
Python正确解释代码就像使用了其他变量一样,因此交换代码等同于:
t1 = b[:,0,0]
t2 = a[:,0,0]
a[:,0,0] = t1
b[:,0,0] = t2
但是,即使此代码也无法正确交换值!这是因为Numpy slices不急切地复制数据,而是创建现有数据的视图。仅在分配切片时执行复制,但在交换时,没有中间缓冲区的副本会破坏您的数据。这就是为什么你不仅需要一个额外的变量,而且还需要一个额外的numpy缓冲区,一般的Python语法都不知道。例如,这可以按预期工作:
t = np.copy(a[:,0,0])
a[:,0,0] = b[:,0,0]
b[:,0,0] = t
答案 1 :(得分:6)
我发现这是最简单的:
a[:,0,0], b[:, 0, 0] = b[:, 0, 0], a[:, 0, 0].copy() #swap
时间比较:
%timeit a[:,0,0], b[:, 0, 0] = b[:, 0, 0], a[:, 0, 0].copy() #swap
The slowest run took 10.79 times longer than the fastest. This could mean that an intermediate result is being cached
1000000 loops, best of 3: 1.75 µs per loop
%timeit t = np.copy(a[:,0,0]); a[:,0,0] = b[:,0,0]; b[:,0,0] = t
The slowest run took 10.88 times longer than the fastest. This could mean that an intermediate result is being cached
100000 loops, best of 3: 2.68 µs per loop
答案 2 :(得分:1)
user4815162342's answer确实是"对"一。但如果你真的在单行之后,请考虑一下:
a[arange(2),0,0], b[arange(2), 0, 0] = b[arange(2), 0, 0], a[arange(2),0,0] #swap
然而效率明显降低:
In [12]: %timeit a[arange(2),0,0], b[arange(2), 0, 0] = b[arange(2), 0, 0], a[arange(2),0,0]
10000 loops, best of 3: 32.2 µs per loop
In [13]: %timeit t = np.copy(a[:,0,0]); a[:,0,0] = b[:,0,0]; b[:,0,0] = t
The slowest run took 4.14 times longer than the fastest. This could mean that an intermediate result is being cached
100000 loops, best of 3: 13.3 µs per loop
(但请注意关于"最慢的运行&#34的说明; ...如果您尝试使用" -n 1 -r 1"来调用%timeit,您会看到更多可比较的结果 - 虽然我的解决方案仍然慢了约50% - 证明是的,缓存正在影响时间)
答案 3 :(得分:-1)
这样可行。
a[:,0,0], b[:, 0, 0] = b[:, 0, 0].copy(), a[:, 0, 0].copy()