Giả sử các mảng sau được đưa ra:
a = array([1,3,5])
b = array([2,4,6])
Làm thế nào để người ta đan xen chúng một cách hiệu quả để người ta có được mảng thứ ba như thế này
c = array([1,2,3,4,5,6])
Có thể cho rằng length(a)==length(b)
.
Giả sử các mảng sau được đưa ra:
a = array([1,3,5])
b = array([2,4,6])
Làm thế nào để người ta đan xen chúng một cách hiệu quả để người ta có được mảng thứ ba như thế này
c = array([1,2,3,4,5,6])
Có thể cho rằng length(a)==length(b)
.
Câu trả lời:
Tôi thích câu trả lời của Josh. Tôi chỉ muốn thêm một giải pháp trần tục hơn, bình thường và dài dòng hơn một chút. Tôi không biết cái nào hiệu quả hơn. Tôi mong đợi họ sẽ có hiệu suất tương tự.
import numpy as np
a = np.array([1,3,5])
b = np.array([2,4,6])
c = np.empty((a.size + b.size,), dtype=a.dtype)
c[0::2] = a
c[1::2] = b
timeit
để kiểm tra mọi thứ nếu một hoạt động cụ thể là nút cổ chai trong mã của bạn. Thường có nhiều cách để thực hiện mọi thứ trong numpy, vì vậy chắc chắn là các đoạn mã hồ sơ.
.reshape
tạo thêm một bản sao của mảng, thì điều đó sẽ giải thích hiệu suất tăng gấp đôi . Tuy nhiên, tôi không nghĩ nó luôn tạo ra một bản sao. Tôi đoán sự khác biệt 5x chỉ dành cho các mảng nhỏ?
.flags
và thử nghiệm .base
giải pháp của tôi, có vẻ như định dạng lại thành định dạng 'F' tạo ra một bản sao ẩn của dữ liệu vstacked, vì vậy đây không phải là một chế độ xem đơn giản như tôi nghĩ. Và kỳ lạ là 5x chỉ dành cho các mảng có kích thước trung bình vì một số lý do.
n
các mặt hàng với n-1
các mặt hàng.
Tôi nghĩ có thể đáng giá để kiểm tra xem các giải pháp hoạt động như thế nào về mặt hiệu suất. Và đây là kết quả:
Điều này cho thấy rõ ràng rằng câu trả lời được ủng hộ và chấp nhận nhiều nhất (câu trả lời của Pauls) cũng là phương án nhanh nhất.
Mã được lấy từ các câu trả lời khác và từ một Câu hỏi và Đáp khác :
# Setup
import numpy as np
def Paul(a, b):
c = np.empty((a.size + b.size,), dtype=a.dtype)
c[0::2] = a
c[1::2] = b
return c
def JoshAdel(a, b):
return np.vstack((a,b)).reshape((-1,),order='F')
def xioxox(a, b):
return np.ravel(np.column_stack((a,b)))
def Benjamin(a, b):
return np.vstack((a,b)).ravel([-1])
def andersonvom(a, b):
return np.hstack( zip(a,b) )
def bhanukiran(a, b):
return np.dstack((a,b)).flatten()
def Tai(a, b):
return np.insert(b, obj=range(a.shape[0]), values=a)
def Will(a, b):
return np.ravel((a,b), order='F')
# Timing setup
timings = {Paul: [], JoshAdel: [], xioxox: [], Benjamin: [], andersonvom: [], bhanukiran: [], Tai: [], Will: []}
sizes = [2**i for i in range(1, 20, 2)]
# Timing
for size in sizes:
func_input1 = np.random.random(size=size)
func_input2 = np.random.random(size=size)
for func in timings:
res = %timeit -o func(func_input1, func_input2)
timings[func].append(res)
%matplotlib notebook
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(1)
ax = plt.subplot(111)
for func in timings:
ax.plot(sizes,
[time.best for time in timings[func]],
label=func.__name__) # you could also use "func.__name__" here instead
ax.set_xscale('log')
ax.set_yscale('log')
ax.set_xlabel('size')
ax.set_ylabel('time [seconds]')
ax.grid(which='both')
ax.legend()
plt.tight_layout()
Chỉ trong trường hợp bạn có sẵn numba, bạn cũng có thể sử dụng nó để tạo một hàm:
import numba as nb
@nb.njit
def numba_interweave(arr1, arr2):
res = np.empty(arr1.size + arr2.size, dtype=arr1.dtype)
for idx, (item1, item2) in enumerate(zip(arr1, arr2)):
res[idx*2] = item1
res[idx*2+1] = item2
return res
Nó có thể nhanh hơn một chút so với các lựa chọn thay thế khác:
roundrobin()
từ các công thức itertools.
Đây là một lớp lót:
c = numpy.vstack((a,b)).reshape((-1,),order='F')
numpy.vstack((a,b)).interweave()
:)
.interleave()
cách cá nhân :)
reshape
?
Đây là một câu trả lời đơn giản hơn một số câu trước
import numpy as np
a = np.array([1,3,5])
b = np.array([2,4,6])
inter = np.ravel(np.column_stack((a,b)))
Sau cái này inter
chứa:
array([1, 2, 3, 4, 5, 6])
Câu trả lời này dường như cũng nhanh hơn một chút:
In [4]: %timeit np.ravel(np.column_stack((a,b)))
100000 loops, best of 3: 6.31 µs per loop
In [8]: %timeit np.ravel(np.dstack((a,b)))
100000 loops, best of 3: 7.14 µs per loop
In [11]: %timeit np.vstack((a,b)).ravel([-1])
100000 loops, best of 3: 7.08 µs per loop
Điều này sẽ xen kẽ / xen kẽ hai mảng và tôi tin rằng nó khá dễ đọc:
a = np.array([1,3,5]) #=> array([1, 3, 5])
b = np.array([2,4,6]) #=> array([2, 4, 6])
c = np.hstack( zip(a,b) ) #=> array([1, 2, 3, 4, 5, 6])
zip
trong một list
để tránh cảnh báo khấu hao
vstack
chắc chắn là một lựa chọn, nhưng giải pháp đơn giản hơn cho trường hợp của bạn có thể là hstack
>>> a = array([1,3,5])
>>> b = array([2,4,6])
>>> hstack((a,b)) #remember it is a tuple of arrays that this function swallows in.
>>> array([1, 3, 5, 2, 4, 6])
>>> sort(hstack((a,b)))
>>> array([1, 2, 3, 4, 5, 6])
và quan trọng hơn, điều này hoạt động với các hình dạng tùy ý a
vàb
Ngoài ra, bạn có thể muốn thử dstack
>>> a = array([1,3,5])
>>> b = array([2,4,6])
>>> dstack((a,b)).flatten()
>>> array([1, 2, 3, 4, 5, 6])
bạn đã có lựa chọn bây giờ!
Người ta cũng có thể thử np.insert
. (Giải pháp được di chuyển từ các mảng xen kẽ numpy )
import numpy as np
a = np.array([1,3,5])
b = np.array([2,4,6])
np.insert(b, obj=range(a.shape[0]), values=a)
Vui lòng xem documentation
và tutorial
để biết thêm thông tin.
Tôi cần phải làm điều này nhưng với các mảng đa chiều dọc theo bất kỳ trục nào. Đây là một chức năng mục đích chung nhanh chóng cho hiệu ứng đó. Nó có chữ ký cuộc gọi giống như np.concatenate
, ngoại trừ việc tất cả các mảng đầu vào phải có chính xác hình dạng tương tự.
import numpy as np
def interleave(arrays, axis=0, out=None):
shape = list(np.asanyarray(arrays[0]).shape)
if axis < 0:
axis += len(shape)
assert 0 <= axis < len(shape), "'axis' is out of bounds"
if out is not None:
out = out.reshape(shape[:axis+1] + [len(arrays)] + shape[axis+1:])
shape[axis] = -1
return np.stack(arrays, axis=axis+1, out=out).reshape(shape)