Suponga que se dan las siguientes matrices:
a = array([1,3,5])
b = array([2,4,6])
¿Cómo se entrelazarían de manera eficiente para obtener una tercera matriz como esta?
c = array([1,2,3,4,5,6])
Se puede suponer que length(a)==length(b).
Suponga que se dan las siguientes matrices:
a = array([1,3,5])
b = array([2,4,6])
¿Cómo se entrelazarían de manera eficiente para obtener una tercera matriz como esta?
c = array([1,2,3,4,5,6])
Se puede suponer que length(a)==length(b).
Respuestas:
Me gusta la respuesta de Josh. Solo quería agregar una solución más mundana, habitual y un poco más detallada. No sé cuál es más eficiente. Espero que tengan un rendimiento similar.
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
timeitpara probar si una operación en particular es un cuello de botella en su código. Por lo general, hay más de una forma de hacer las cosas en numpy, por lo que definitivamente hay fragmentos de código de perfil.
.reshapecrea una copia adicional de la matriz, eso explicaría un impacto de rendimiento 2x. Sin embargo, no creo que siempre tenga una copia. Supongo que la diferencia de 5x es solo para arreglos pequeños.
.flagsy probando .basemi solución, parece que la remodelación al formato 'F' crea una copia oculta de los datos vstacked, por lo que no es una vista simple como pensé que sería. Y extrañamente, el 5x es solo para matrices de tamaño intermedio por alguna razón.
nartículos con n-1artículos.
Pensé que valdría la pena comprobar el rendimiento de las soluciones. Y este es el resultado:
Esto muestra claramente que la respuesta más votada y aceptada (la respuesta de Paul) es también la opción más rápida.
El código se tomó de las otras respuestas y de otra sesión de preguntas y respuestas :
# 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()
En caso de que tenga numba disponible, también puede usarlo para crear una función:
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
Podría ser un poco más rápido que las otras alternativas:
roundrobin()las recetas de itertools.
Aquí hay un resumen:
c = numpy.vstack((a,b)).reshape((-1,),order='F')
numpy.vstack((a,b)).interweave():)
.interleave()personalmente :)
reshape?
Aquí hay una respuesta más simple que algunas de las anteriores.
import numpy as np
a = np.array([1,3,5])
b = np.array([2,4,6])
inter = np.ravel(np.column_stack((a,b)))
Después de esto intercontiene:
array([1, 2, 3, 4, 5, 6])
Esta respuesta también parece ser ligeramente más rápida:
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
Esto intercalará / entrelazará las dos matrices y creo que es bastante legible:
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])
zipen una listadvertencia para evitar la depreciación
Tal vez esto sea más legible que la solución de @ JoshAdel:
c = numpy.vstack((a,b)).ravel([-1])
ravel's orderargumento a la documentación es uno de C, F, A, o K. Creo que realmente lo desea .ravel('F'), para el pedido de FORTRAN (primera columna)
vstack seguro es una opción, pero una solución más sencilla para su caso podría ser 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])
y lo que es más importante, esto funciona para formas arbitrarias de ayb
También es posible que desee probar dstack
>>> a = array([1,3,5])
>>> b = array([2,4,6])
>>> dstack((a,b)).flatten()
>>> array([1, 2, 3, 4, 5, 6])
¡Tienes opciones ahora!
Otro one-liner: np.vstack((a,b)).T.ravel()
Uno más:np.stack((a,b),1).ravel()
También se puede intentar np.insert. (Solución migrada de matrices numpy de 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)
Consulte el documentationy tutorialpara obtener más información.
Necesitaba hacer esto pero con matrices multidimensionales a lo largo de cualquier eje. Aquí hay una función rápida de propósito general a tal efecto. Tiene la misma firma de llamada que np.concatenate, excepto que todas las matrices de entrada deben tener exactamente la misma forma.
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)