Припустимо, що наведені такі масиви:
a = array([1,3,5])
b = array([2,4,6])
Як можна їх ефективно переплести, щоб отримати такий третій масив
c = array([1,2,3,4,5,6])
Можна припустити, що length(a)==length(b).
Припустимо, що наведені такі масиви:
a = array([1,3,5])
b = array([2,4,6])
Як можна їх ефективно переплести, щоб отримати такий третій масив
c = array([1,2,3,4,5,6])
Можна припустити, що length(a)==length(b).
Відповіді:
Мені подобається відповідь Джоша. Я просто хотів додати більш повсякденне, звичне і трохи більш багатослівне рішення. Я не знаю, що є більш ефективним. Я сподіваюся, вони будуть мати подібні показники.
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щоб перевірити ситуацію, якщо певна операція є вузьким місцем у вашому коді. Зазвичай існує кілька способів робити щось у numpy, тому, безперечно, фрагменти коду профілю.
.reshapeстворить додаткову копію масиву, це пояснювало б збільшення продуктивності у 2 рази. Однак я не думаю, що це завжди робить копію. Я здогадуюсь, що різниця в 5 разів стосується лише малих масивів?
.flagsі тестуючи .baseмоє рішення, схоже, що зміна формату на формат F створює приховану копію даних vstacked, тому це не простий вигляд, як я думав, буде. І дивно, що 5x чомусь призначений лише для масивів середнього розміру.
nпредмети з n-1предметами.
Я вважав, що варто перевірити, як працюють рішення з точки зору продуктивності. І ось результат:
Це наочно показує, що найбільш схвалена та прийнята відповідь (відповідь Паулса) - це також найшвидший варіант.
Код взятий з інших відповідей та з інших запитань :
# 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()
Про всяк випадок, якщо у вас є numba, ви також можете використовувати це для створення функції:
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
Це може бути трохи швидше, ніж інші альтернативи:
roundrobin()рецептів itertools.
Ось однокласний вкладиш:
c = numpy.vstack((a,b)).reshape((-1,),order='F')
numpy.vstack((a,b)).interweave():)
.interleave()особисто :)
reshape?
Ось простіша відповідь, ніж деякі з попередніх
import numpy as np
a = np.array([1,3,5])
b = np.array([2,4,6])
inter = np.ravel(np.column_stack((a,b)))
Після цього interміститься:
array([1, 2, 3, 4, 5, 6])
Ця відповідь також виявляється незначно швидшою:
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
Це дозволить чергувати / чергувати два масиви, і я вважаю, що це цілком читабельно:
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у, listщоб уникнути попередження про амортизацію
Можливо, це читабельніше, ніж рішення @ JoshAdel:
c = numpy.vstack((a,b)).ravel([-1])
ravel«S orderаргумент в документації є одним з C, F, Aабо K. Думаю, ви дійсно хочете .ravel('F'), для замовлення FORTRAN (перша колонка)
vstack Звичайно, це варіант, але більш простим рішенням для вашої справи може бути 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])
і що більш важливо це працює для довільних форм aіb
Також ви можете спробувати dstack
>>> a = array([1,3,5])
>>> b = array([2,4,6])
>>> dstack((a,b)).flatten()
>>> array([1, 2, 3, 4, 5, 6])
у вас зараз є варіанти!
Можна також спробувати np.insert. (Рішення перенесено з масивів Numpy Interleave )
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)
Будь ласка , дивіться documentationі tutorialдля отримання додаткової інформації.
Мені потрібно було це зробити, але з багатовимірними масивами вздовж будь-якої осі. Ось швидка загальна функція для цього. Він має той самий підпис виклику np.concatenate, за винятком того, що всі вхідні масиви повинні мати абсолютно однакову форму.
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)