Переплетение двух массивов - PullRequest
57 голосов
/ 18 марта 2011

Предположим, что заданы следующие массивы:

a = array([1,3,5])
b = array([2,4,6])

Как эффективно их переплетать, чтобы получить третий массив, подобный этому

c = array([1,2,3,4,5,6])

Можно предположить, что length(a)==length(b).

Ответы [ 9 ]

96 голосов
/ 18 марта 2011

Мне нравится ответ Джоша.Я просто хотел добавить более приземленное, обычное и немного более подробное решение.Я не знаю, что является более эффективным.Я ожидаю, что они будут иметь аналогичную производительность.

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
34 голосов
/ 18 марта 2011

Вот одна строка:

c = numpy.vstack((a,b)).reshape((-1,),order='F')
28 голосов
/ 28 января 2018

Я подумал, что стоит проверить, как решения работают с точки зрения производительности. И вот результат:

enter image description here

Это ясно показывает, что наиболее одобренный и принятый ответ (ответ Павла) также является самым быстрым вариантом.

Код был взят из других ответов и из другого Q & A :

# 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

Может быть немного быстрее, чем другие альтернативы:

enter image description here

18 голосов
/ 31 мая 2015

Вот более простой ответ, чем некоторые из предыдущих

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
5 голосов
/ 16 апреля 2013

Это будет чередовать / чередовать два массива, и я считаю, что это вполне читабельно:

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])
5 голосов
/ 18 марта 2011

Может быть, это более читабельно, чем решение @ JoshAdel:

c = numpy.vstack((a,b)).ravel([-1])
3 голосов
/ 30 ноября 2017

Улучшение ответа @ xioxox:

import numpy as np
a = np.array([1,3,5])
b = np.array([2,4,6])
inter = np.ravel((a,b), order='F')
1 голос
/ 19 марта 2011

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])

У вас есть варианты сейчас!

0 голосов
/ 28 января 2018

Можно также попробовать np.insert.(Решение перенесено из чередующихся массивов 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...