Припустимо, що наведені такі масиви:
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)