Как насчет того же вопроса, но вы пытаетесь чередовать матрицы. То есть a и b трехмерны и не обязательно имеют одинаковый размер в первом измерении. Примечание: следует чередовать только первое измерение.
Geronimo
Ответы:
144
Мне нравится ответ Джоша. Я просто хотел добавить более приземленное, обычное и немного более подробное решение. Не знаю, что эффективнее. Я ожидаю, что у них будет аналогичная производительность.
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
Если скорость действительно не важна, я бы согласился с этим, потому что он гораздо более понятен, что важно, если кто-нибудь когда-нибудь собирается взглянуть на это снова.
Джон Сальватье
6
+1 Я поигрался с таймингами, и ваш код на удивление кажется в 2-5 раз быстрее в зависимости от входных данных. Я по-прежнему считаю, что эффективность этих типов операций не интуитивно понятна, поэтому всегда стоит использовать их timeitдля проверки того, является ли конкретная операция узким местом в вашем коде. Обычно в numpy есть несколько способов сделать что-то, поэтому определенно профилируйте фрагменты кода.
JoshAdel
@JoshAdel: Думаю, если будет .reshapeсоздана дополнительная копия массива, это объяснит удвоение производительности. Однако я не думаю, что он всегда копирует. Я предполагаю, что разница в 5 раз только для небольших массивов?
Пол
глядя на мое решение .flagsи тестируя .baseего, похоже, что преобразование в формат «F» создает скрытую копию данных, объединенных в стек, так что это не простое представление, как я думал. И, как ни странно, 5x по какой-то причине предназначен только для массивов среднего размера.
JoshAdel
Еще одно преимущество этого ответа в том, что он не ограничен массивами одинаковой длины. Он мог переплетать nпредметы с n-1предметами.
EliadL
63
Я подумал, что стоит проверить, как решения работают с точки зрения производительности. И вот результат:
Вау, это так нечитабельно :) Это один из тех случаев, когда, если вы не напишете в коде правильный комментарий, это может кого-то с ума свести.
Илья Коган
10
Это всего лишь две общие команды numpy, связанные вместе. Я бы не подумал, что это так нечитабельно, хотя комментарий никогда не повредит.
JoshAdel
1
@JohnAdel, ну это не так numpy.vstack((a,b)).interweave():)
Илья Коган
6
@Ilya: Я бы .interleave()лично позвонил в функцию :)
JoshAdel
Что reshapeделать?
Даниэль
23
Вот более простой ответ, чем некоторые из предыдущих
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
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])
-1 к первому ответу, потому что вопрос не имеет ничего общего с сортировкой. +1 ко второму ответу, это лучшее, что я когда-либо видел. Вот почему несколько решений следует публиковать в виде нескольких ответов. Пожалуйста, разбейте его на несколько ответов.
endolith
1
Мне нужно было это сделать, но с многомерными массивами по любой оси. Вот быстрая функция общего назначения на этот счет. Он имеет ту же сигнатуру вызова, что и np.concatenate, за исключением того, что все входные массивы должны иметь точно такую же форму.
import numpy as np
definterleave(arrays, axis=0, out=None):
shape = list(np.asanyarray(arrays[0]).shape)
if axis < 0:
axis += len(shape)
assert0 <= axis < len(shape), "'axis' is out of bounds"if out isnotNone:
out = out.reshape(shape[:axis+1] + [len(arrays)] + shape[axis+1:])
shape[axis] = -1return np.stack(arrays, axis=axis+1, out=out).reshape(shape)
+1 для такого обобщенного рецепта (работает с n-dim, чередуется по любой оси, работает для любого количества входных массивов, принимает необязательный outаргумент и работает для массивов подклассов). Лично я бы предпочел axisпо умолчанию, -1а не 0, но, возможно, это только я. И вы можете захотеть дать ссылку на этот ваш ответ из этого вопроса , который фактически требует, чтобы входные массивы были n-мерными.
fountainhead
1
Еще одна строка: np.vstack((a,b)).T.ravel()
Еще одна:np.stack((a,b),1).ravel()
Ответы:
Мне нравится ответ Джоша. Я просто хотел добавить более приземленное, обычное и немного более подробное решение. Не знаю, что эффективнее. Я ожидаю, что у них будет аналогичная производительность.
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
создана дополнительная копия массива, это объяснит удвоение производительности. Однако я не думаю, что он всегда копирует. Я предполагаю, что разница в 5 раз только для небольших массивов?.flags
и тестируя.base
его, похоже, что преобразование в формат «F» создает скрытую копию данных, объединенных в стек, так что это не простое представление, как я думал. И, как ни странно, 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
«Sorder
аргумент в документации является одним изC
,F
,A
илиK
. Я думаю, вы действительно хотите.ravel('F')
заказать FORTRAN (первая колонка)Улучшение ответа @xioxox:
import numpy as np a = np.array([1,3,5]) b = np.array([2,4,6]) inter = np.ravel((a,b), order='F')
источник
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.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)
источник
out
аргумент и работает для массивов подклассов). Лично я бы предпочелaxis
по умолчанию,-1
а не0
, но, возможно, это только я. И вы можете захотеть дать ссылку на этот ваш ответ из этого вопроса , который фактически требует, чтобы входные массивы были n-мерными.Еще одна строка:
np.vstack((a,b)).T.ravel()
Еще одна:
np.stack((a,b),1).ravel()
источник
Еще можно попробовать
np.insert
. (Решение перенесено из массивов Interleave 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)
Пожалуйста, смотрите
documentation
иtutorial
для получения дополнительной информации.источник