web-dev-qa-db-fra.com

Entrelacement de deux tableaux numpy

Supposons que les tableaux suivants sont donnés:

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

Comment les entrelacer efficacement pour obtenir un troisième tableau comme celui-ci

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

On peut supposer que length(a)==length(b).

51
dzhelil

J'aime la réponse de Josh. Je voulais juste ajouter une solution plus banale, habituelle et légèrement plus verbeuse. Je ne sais pas lequel est le plus efficace. Je pense qu'ils auront des performances similaires.

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
85
Paul

Voici un one-liner:

c = numpy.vstack((a,b)).reshape((-1,),order='F')
32
JoshAdel

J'ai pensé qu'il pourrait être utile de vérifier comment les solutions fonctionnaient en termes de performances. Et voici le résultat:

enter image description here

Cela montre clairement que la réponse la plus votée et acceptée (réponse de Paul) est également l’option la plus rapide.

Le code provient des autres réponses et de une autre question/réponse :

# 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()

Juste au cas où vous auriez un numba disponible, vous pourriez aussi l'utiliser pour créer une fonction:

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

Il pourrait être légèrement plus rapide que les autres alternatives:

enter image description here

19
MSeifert

Voici une réponse plus simple que certaines des précédentes

import numpy as np
a = np.array([1,3,5])
b = np.array([2,4,6])
inter = np.ravel(np.column_stack((a,b)))

Après cette inter contient:

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

Cette réponse semble également être légèrement plus rapide:

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
17
xioxox

Cela entrelacera/entrelacera les deux tableaux et je crois que c'est assez lisible:

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
andersonvom

Peut-être que ceci est plus lisible que la solution de @ JoshAdel:

c = numpy.vstack((a,b)).ravel([-1])
4
Benjamin

Améliorer la réponse de @ xioxox:

import numpy as np
a = np.array([1,3,5])
b = np.array([2,4,6])
inter = np.ravel((a,b), order='F')
2
Will

vstack sûr est une option, mais une solution plus simple pour votre cas pourrait être la 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])

et plus important encore, cela fonctionne pour les formes arbitraires de a et b

Aussi, vous voudrez peut-être essayer dstack 

>>> a = array([1,3,5])
>>> b = array([2,4,6])
>>> dstack((a,b)).flatten()
>>> array([1, 2, 3, 4, 5, 6])

vous avez des options maintenant!

1
bhanukiran

On peut aussi essayer np.insert. (Solution migrée à partir de tableaux 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)

Veuillez consulter les documentation et tutorial pour plus d'informations. 

0
Tai