Cet article explique comment concatรฉner plusieurs tableaux NumPy ( ๐งโ๐โ๐โ๐ซโ๐ซโ๐โ๐ฒโ ) ร l’aide de fonctions telles que ๐งโ๐ฉโ.๐โ๐จโ๐งโ๐โ๐โ๐ญโ๐โ๐งโ๐โ๐ญโ๐โ() et ๐งโ๐ฉโ.๐ฌโ๐ญโ๐โ๐โ๐คโ() .
๐งโ๐ฉโ.๐โ๐จโ๐งโ๐โ๐โ๐ญโ๐โ๐งโ๐โ๐ญโ๐โ() concatรจne le long d’un axe existant, tandis que ๐งโ๐ฉโ.๐ฌโ๐ญโ๐โ๐โ๐คโ() concatรจne le long d’un nouvel axe. Par exemple, ๐งโ๐ฉโ.๐โ๐จโ๐งโ๐โ๐โ๐ญโ๐โ๐งโ๐โ๐ญโ๐โ() peut concatรฉner des tableaux 2D verticalement ou horizontalement, et ๐งโ๐ฉโ.๐ฌโ๐ญโ๐โ๐โ๐คโ() peut empiler des tableaux 2D pour crรฉer un tableau 3D.
Bien que ๐งโ๐ฉโ.๐โ๐จโ๐งโ๐โ๐โ๐ญโ๐โ๐งโ๐โ๐ญโ๐โ() et ๐งโ๐ฉโ.๐ฌโ๐ญโ๐โ๐โ๐คโ() รชtre polyvalent pour une large gamme d’applications, il est รฉgalement bรฉnรฉfique d’รชtre interactif avec ๐งโ๐ฉโ.๐โ๐ฅโ๐จโ๐โ๐คโ() , ๐งโ๐ฉโ.๐ฏโ๐ฌโ๐ญโ๐โ๐โ๐คโ() , ๐งโ๐ฉโ.๐กโ๐ฌโ๐ญโ๐โ๐โ๐คโ() et ๐งโ๐ฉโ.๐โ๐ฌโ๐ญโ๐โ๐โ๐คโ() , en particulier lorsque vous travaillez avec des tableaux 2D.
- ๐งโ๐ฉโ.๐โ๐จโ๐งโ๐โ๐โ๐ญโ๐โ๐งโ๐โ๐ญโ๐โ() concatรจne des tableaux le long d’un axe existant
- ๐งโ๐ฉโ.๐ฌโ๐ญโ๐โ๐โ๐คโ() concatรจne les tableaux le long d’un nouvel axe
- ๐งโ๐ฉโ.๐โ๐ฅโ๐จโ๐โ๐คโ() concatรจne les tableaux selon l’agencement spรฉcifiรฉ
- ๐งโ๐ฉโ.๐ฏโ๐ฌโ๐ญโ๐โ๐โ๐คโ() concatรจne les tableaux verticalement
- ๐งโ๐ฉโ.๐กโ๐ฌโ๐ญโ๐โ๐โ๐คโ() concatรจne les tableaux horizontalement
- ๐งโ๐ฉโ.๐โ๐ฌโ๐ญโ๐โ๐โ๐คโ() concatรจne les tableaux dans le sens de la profondeur
D’autres mรฉthodes, telles que ๐งโ๐ฉโ.๐ซโ_[] et ๐งโ๐ฉโ.๐โ_[] , sont รฉgalement disponibles mais ne sont pas abordรฉes dans cet article. Pour plus de dรฉtails, reportez-vous ร la documentation officielle :
Consultez les articles suivants pour savoir comment diviser un ๐งโ๐โ๐โ๐ซโ๐ซโ๐โ๐ฒโ ou ajouter des valeurs ร un ๐งโ๐โ๐โ๐ซโ๐ซโ๐โ๐ฒโ .
- NumPy : Diviser un tableau avec np.split, np.vsplit, np.hsplit, etc.
- NumPy : append() pour ajouter des valeurs ร un tableau
- NumPy : insรฉrer des รฉlรฉments, des lignes et des colonnes dans un tableau avec np.insert()
La version de NumPy utilisรฉe dans cet article est la suivante. Notez que les fonctionnalitรฉs peuvent varier selon les versions.
import numpy as np print(np.__version__) # 1.26.1
๐งโ๐ฉโ.๐โ๐จโ๐งโ๐โ๐โ๐ญโ๐โ๐งโ๐โ๐ญโ๐โ() concatรจne des tableaux le long d’un axe existant
๐งโ๐ฉโ.๐โ๐จโ๐งโ๐โ๐โ๐ญโ๐โ๐งโ๐โ๐ญโ๐โ() concatรจne des tableaux le long d’un axe existant.
Spรฉcifiez la liste des tableaux ร concatรฉner
Considรฉrez les tableaux suivants comme exemple.
a1 = np.ones((2, 3), int) print(a1) # [[1 1 1] # [1 1 1]] a2 = np.full((2, 3), 2) print(a2) # [[2 2 2] # [2 2 2]]
Reportez-vous ร l’article suivant pour ๐งโ๐ฉโ.๐จโ๐งโ๐โ๐ฌโ() et ๐งโ๐ฉโ.๐โ๐ฎโ๐ฅโ๐ฅโ() .
Spรฉcifiez la liste des tableaux comme premier argument. Vous pouvez รฉgalement utiliser un tuple ร la place d’une liste.
print(np.concatenate([a1, a2])) # [[1 1 1] # [1 1 1] # [2 2 2] # [2 2 2]]
Pour plus de trois tableaux, augmentez simplement le nombre d’รฉlรฉments dans la liste ou le tuple spรฉcifiรฉ comme premier argument.
a3 = np.full((2, 3), 3) print(a3) # [[3 3 3] # [3 3 3]] print(np.concatenate([a1, a2, a3])) # [[1 1 1] # [1 1 1] # [2 2 2] # [2 2 2] # [3 3 3] # [3 3 3]]
Spรฉcifiez l’axe ร concatรฉner : ๐โ๐ฑโ๐ขโ๐ฌโ
Spรฉcifiez l’axe ร concatรฉner comme deuxiรจme argument, ๐โ๐ฑโ๐ขโ๐ฌโ . La valeur par dรฉfaut est ๐โ๐ฑโ๐ขโ๐ฌโ=0 .
Pour les tableaux 2D, ๐โ๐ฑโ๐ขโ๐ฌโ=0 concatรจne verticalement et ๐โ๐ฑโ๐ขโ๐ฌโ=1 concatรจne horizontalement.
a1 = np.ones((2, 3), int) print(a1) # [[1 1 1] # [1 1 1]] a2 = np.full((2, 3), 2) print(a2) # [[2 2 2] # [2 2 2]] print(np.concatenate([a1, a2], 0)) # [[1 1 1] # [1 1 1] # [2 2 2] # [2 2 2]] print(np.concatenate([a1, a2], 1)) # [[1 1 1 2 2 2] # [1 1 1 2 2 2]]
La spรฉcification d’un axe inexistant entraรฎnera une erreur. Pour concatรฉner le long d’un nouvel axe, par exemple lors de l’empilement de tableaux 2D pour crรฉer un tableau 3D, utilisez ๐งโ๐ฉโ.๐ฌโ๐ญโ๐โ๐โ๐คโ() ou d’autres fonctions similaires qui seront abordรฉes plus tard.
# print(np.concatenate([a1, a2], 2)) # AxisError: axis 2 is out of bounds for array of dimension 2
Une erreur se produit si les tailles des axes autres que l’axe de concatรฉnation ne correspondent pas. Les parties manquantes ne sont pas remplies avec N๐โN .
a2_ = np.full((3, 3), 2) print(a2_) # [[2 2 2] # [2 2 2] # [2 2 2]] print(np.concatenate([a1, a2_], 0)) # [[1 1 1] # [1 1 1] # [2 2 2] # [2 2 2] # [2 2 2]] # print(np.concatenate([a1, a2_], 1)) # ValueError: all the input array dimensions except for the concatenation axis must match exactly, but along dimension 0, the array at index 0 has size 2 and the array at index 1 has size 3
La mรชme chose a choisi s’appliquer aux tableaux de dimensions autres que deux : spรฉcifier l’axe de concatรฉnation avec le deuxiรจme argument ๐โ๐ฑโ๐ขโ๐ฌโ , en notant que la concatรฉnation ne peut pas รชtre effectuรฉe sur des axes inexistants.
a1 = np.ones(3, int) print(a1) # [1 1 1] a2 = np.full(3, 2) print(a2) # [2 2 2] print(np.concatenate([a1, a2], 0)) # [1 1 1 2 2 2] # print(np.concatenate([a1, a2], 1)) # AxisError: axis 1 is out of bounds for array of dimension 1
Une erreur se produit si les tableaux d’entrรฉe ont un nombre de dimensions diffรฉrent.
a1 = np.ones((2, 3), int) print(a1) # [[1 1 1] # [1 1 1]] a2 = np.full(3, 2) print(a2) # [2 2 2] # print(np.concatenate([a1, a2], 0)) # ValueError: all the input arrays must have same number of dimensions, but the array at index 0 has 2 dimension(s) and the array at index 1 has 1 dimension(s)
Il est possible de concatรฉner verticalement des tableaux 1D et 2D en utilisant ๐งโ๐ฉโ.๐โ๐ฅโ๐จโ๐โ๐คโ() ou ๐งโ๐ฉโ.๐ฏโ๐ฌโ๐ญโ๐โ๐โ๐คโ() comme dรฉcrit plus longe.
๐งโ๐ฉโ.๐ฌโ๐ญโ๐โ๐โ๐คโ() concatรจne les tableaux le long d’un nouvel axe
Contrairement ร ๐งโ๐ฉโ.๐โ๐จโ๐งโ๐โ๐โ๐ญโ๐โ๐งโ๐โ๐ญโ๐โ() , qui concatรจne des tableaux le long d’un axe existant, ๐งโ๐ฉโ.๐ฌโ๐ญโ๐โ๐โ๐คโ() empile les tableaux le long d’un nouvel axe.
Dans ๐งโ๐ฉโ.๐ฌโ๐ญโ๐โ๐โ๐คโ() , le premier argument est la liste des tableaux et le deuxiรจme argument, ๐โ๐ฑโ๐ขโ๐ฌโ , spรฉcifique l’axe de concatรฉnation dans le tableau rรฉsultant.
Pour les tableaux 1D
Considรฉrez les tableaux 1D suivants comme exemples.
a1 = np.ones(3, int) print(a1) # [1 1 1] a2 = np.full(3, 2) print(a2) # [2 2 2]
รtant donnรฉ que ๐งโ๐ฉโ.๐ฌโ๐ญโ๐โ๐โ๐คโ() concatรจne les tableaux le long d’un nouvel axe, le rรฉsultat est un tableau 2D, une dimension plus haute que l’entrรฉe.
La valeur par dรฉfaut est ๐โ๐ฑโ๐ขโ๐ฌโ=0 . La spรฉcification d’un axe qui n’existe pas dans le tableau rรฉsultant entraรฎnera une erreur.
print(np.stack([a1, a2])) # [[1 1 1] # [2 2 2]] print(np.stack([a1, a2], 0)) # [[1 1 1] # [2 2 2]] print(np.stack([a1, a2], 1)) # [[1 2] # [1 2] # [1 2]] # print(np.stack([a1, a2], 2)) # AxisError: axis 2 is out of bounds for array of dimension 2
Le paramรจtre ๐โ๐ฑโ๐ขโ๐ฌโ=-1 spรฉcifique le dernier axe, รฉquivalent ร ๐โ๐ฑโ๐ขโ๐ฌโ=1 dans cet exemple.
print(np.stack([a1, a2], -1)) # [[1 2] # [1 2] # [1 2]]
Une erreur se produit si les tableaux d’entrรฉe ont des formes diffรฉrentes.
a2_ = np.full(4, 2) print(a2_) # [2 2 2 2] # print(np.stack([a1, a2_])) # ValueError: all input arrays must have the same shape
Pour les tableaux 2D
Ensuite, considรฉrez les tableaux 2D suivants comme exemples.
a1 = np.ones((3, 4), int) print(a1) # [[1 1 1 1] # [1 1 1 1] # [1 1 1 1]] a2 = np.full((3, 4), 2) print(a2) # [[2 2 2 2] # [2 2 2 2] # [2 2 2 2]]
Similairement ร l’opรฉration sur les tableaux 1D, l’utilisation de tableaux 2D comme entrรฉe gรฉnรจre un tableau 3D, une dimension plus haute que l’entrรฉe. Comprendre la forme du tableau rรฉsultant est essentiel pour comprendre ce concept.
print(np.stack([a1, a2])) # [[[1 1 1 1] # [1 1 1 1] # [1 1 1 1]] # # [[2 2 2 2] # [2 2 2 2] # [2 2 2 2]]] print(np.stack([a1, a2], 0)) # [[[1 1 1 1] # [1 1 1 1] # [1 1 1 1]] # # [[2 2 2 2] # [2 2 2 2] # [2 2 2 2]]] print(np.stack([a1, a2], 0).shape) # (2, 3, 4)
print(np.stack([a1, a2], 1)) # [[[1 1 1 1] # [2 2 2 2]] # # [[1 1 1 1] # [2 2 2 2]] # # [[1 1 1 1] # [2 2 2 2]]] print(np.stack([a1, a2], 1).shape) # (3, 2, 4) print(np.stack([a1, a2], 1)[:, 0, :]) # [[1 1 1 1] # [1 1 1 1] # [1 1 1 1]] print(np.stack([a1, a2], 1)[:, 1, :]) # [[2 2 2 2] # [2 2 2 2] # [2 2 2 2]]
print(np.stack([a1, a2], 2)) # [[[1 2] # [1 2] # [1 2] # [1 2]] # # [[1 2] # [1 2] # [1 2] # [1 2]] # # [[1 2] # [1 2] # [1 2] # [1 2]]] print(np.stack([a1, a2], 2).shape) # (3, 4, 2) print(np.stack([a1, a2], 2)[:, :, 0]) # [[1 1 1 1] # [1 1 1 1] # [1 1 1 1]] print(np.stack([a1, a2], 2)[:, :, 1]) # [[2 2 2 2] # [2 2 2 2] # [2 2 2 2]]
La spรฉcification d’un axe qui n’existe pas dans le tableau rรฉsultant entraรฎnera une erreur.
# print(np.stack([a1, a2], 3)) # AxisError: axis 3 is out of bounds for array of dimension 3
Le paramรจtre ๐โ๐ฑโ๐ขโ๐ฌโ=-1 spรฉcifique le dernier axe, รฉquivalent ร ๐โ๐ฑโ๐ขโ๐ฌโ=2 dans cet exemple.
print(np.stack([a1, a2], -1)) # [[[1 2] # [1 2] # [1 2] # [1 2]] # # [[1 2] # [1 2] # [1 2] # [1 2]] # # [[1 2] # [1 2] # [1 2] # [1 2]]] print(np.stack([a1, a2], -1).shape) # (3, 4, 2)
Une erreur se produit si les tableaux d’entrรฉe ont des formes diffรฉrentes.
a2_ = np.full((2, 3), 2) print(a2_) # [[2 2 2] # [2 2 2]] # print(np.stack([a1, a2_])) # ValueError: all input arrays must have the same shape
Le mรชme concept s’applique ร des cas encore plus multidimensionnels.
๐งโ๐ฉโ.๐โ๐ฅโ๐จโ๐โ๐คโ() concatรจne les tableaux selon l’agencement spรฉcifiรฉ
๐งโ๐ฉโ.๐โ๐ฅโ๐จโ๐โ๐คโ() vous permet de concatรฉner des tableaux de maniรจre plus intuitive.
Spรฉcifiez une liste indiquant comment les tableaux d’origine sont disposรฉs.
Par exemple, la spรฉcification d’une liste de tableaux ร placer cรดte ร cรดte entraรฎne une concatรฉnation horizontale selon l’ordre.
a1 = np.ones((2, 3), int) print(a1) # [[1 1 1] # [1 1 1]] a2 = np.full((2, 3), 2) print(a2) # [[2 2 2] # [2 2 2]] print(np.block([a1, a2])) # [[1 1 1 2 2 2] # [1 1 1 2 2 2]]
Une liste 2D (liste imbriquรฉe) permet รฉgalement de prรฉciser les dispositions verticales.
print(np.block([[a1], [a2]])) # [[1 1 1] # [1 1 1] # [2 2 2] # [2 2 2]] print(np.block([[a1, a2], [a2, a1]])) # [[1 1 1 2 2 2] # [1 1 1 2 2 2] # [2 2 2 1 1 1] # [2 2 2 1 1 1]]
La spรฉcification d’une liste 3D gรฉnรจre un rรฉsultat 3D.
print(np.block([[[a1]], [[a2]]])) # [[[1 1 1] # [1 1 1]] # # [[2 2 2] # [2 2 2]]] print(np.block([[[a1]], [[a2]]]).shape) # (2, 2, 3)
Il est รฉgalement possible de combiner des tableaux 1D et 2D ; cependant, pour รฉviter les erreurs, la profondeur d’imbrication doit รชtre cohรฉrente, mรชme en combinant un seul tableau, comme le dรฉmontrer [๐โ3] dans l’exemple suivant.
a3 = np.full(6, 3) print(a3) # [3 3 3 3 3 3] print(np.block([[a1, a2], [a3]])) # [[1 1 1 2 2 2] # [1 1 1 2 2 2] # [3 3 3 3 3 3]] # print(np.block([[a1, a2], a3])) # ValueError: List depths are mismatched. First element was at depth 2, but there is an element at depth 1 (arrays[1])
Une erreur se produit s’il y a une incompatibilitรฉ dans le nombre d’รฉlรฉments.
# print(np.block([[a1, a2, a3]])) # ValueError: all the input array dimensions except for the concatenation axis must match exactly, but along dimension 0, the array at index 0 has size 2 and the array at index 2 has size 1
๐งโ๐ฉโ.๐ฏโ๐ฌโ๐ญโ๐โ๐โ๐คโ() concatรจne les tableaux verticalement
๐งโ๐ฉโ.๐ฏโ๐ฌโ๐ญโ๐โ๐โ๐คโ() concatรจne les tableaux verticalement, ce qui รฉquivaut essentiellement ร ๐งโ๐ฉโ.๐โ๐จโ๐งโ๐โ๐โ๐ญโ๐โ๐งโ๐โ๐ญโ๐โ() avec ๐โ๐ฑโ๐ขโ๐ฌโ=0 .
a1 = np.ones((2, 3), int) print(a1) # [[1 1 1] # [1 1 1]] a2 = np.full((2, 3), 2) print(a2) # [[2 2 2] # [2 2 2]] print(np.vstack([a1, a2])) # [[1 1 1] # [1 1 1] # [2 2 2] # [2 2 2]] print(np.concatenate([a1, a2], 0)) # [[1 1 1] # [1 1 1] # [2 2 2] # [2 2 2]]
Cependant, ๐งโ๐ฉโ.๐ฏโ๐ฌโ๐ญโ๐โ๐โ๐คโ() รฉtend les tableaux d’entrรฉe 1D en 2D (forme (N, ) en (1, N) ), permettant la concatรฉnation de tableaux 1D en un tableau 2D ou la concatรฉnation de tableaux 1D et 2D.
a1 = np.ones(3, int) print(a1) # [1 1 1] a2 = np.full(3, 2) print(a2) # [2 2 2] print(np.vstack([a1, a2])) # [[1 1 1] # [2 2 2]] print(np.concatenate([a1.reshape(1, -1), a2.reshape(1, -1)], 0)) # [[1 1 1] # [2 2 2]]
a2_2d = np.full((2, 3), 2) print(a2_2d) # [[2 2 2] # [2 2 2]] print(np.vstack([a1, a2_2d])) # [[1 1 1] # [2 2 2] # [2 2 2]] print(np.concatenate([a1.reshape(1, -1), a2_2d], 0)) # [[1 1 1] # [2 2 2] # [2 2 2]]
๐งโ๐ฉโ.๐กโ๐ฌโ๐ญโ๐โ๐โ๐คโ() concatรจne les tableaux horizontalement
๐งโ๐ฉโ.๐กโ๐ฌโ๐ญโ๐โ๐โ๐คโ() concatรจne les tableaux horizontalement, ce qui รฉquivaut essentiellement ร ๐งโ๐ฉโ.๐โ๐จโ๐งโ๐โ๐โ๐ญโ๐โ๐งโ๐โ๐ญโ๐โ() avec ๐โ๐ฑโ๐ขโ๐ฌโ=1 .
a1 = np.ones((2, 3), int) print(a1) # [[1 1 1] # [1 1 1]] a2 = np.full((2, 3), 2) print(a2) # [[2 2 2] # [2 2 2]] print(np.hstack([a1, a2])) # [[1 1 1 2 2 2] # [1 1 1 2 2 2]] print(np.concatenate([a1, a2], 1)) # [[1 1 1 2 2 2] # [1 1 1 2 2 2]]
Cependant, pour les tableaux 1D, il appelle ๐งโ๐ฉโ.๐โ๐จโ๐งโ๐โ๐โ๐ญโ๐โ๐งโ๐โ๐ญโ๐โ() avec ๐โ๐ฑโ๐ขโ๐ฌโ=0 .
a1 = np.ones(3, int) print(a1) # [1 1 1] a2 = np.full(3, 2) print(a2) # [2 2 2] print(np.hstack([a1, a2])) # [1 1 1 2 2 2] print(np.concatenate([a1, a2], 0)) # [1 1 1 2 2 2]
Contrairement ร ๐งโ๐ฉโ.๐ฏโ๐ฌโ๐ญโ๐โ๐โ๐คโ() , les tableaux 1D ne sont pas dรฉveloppรฉs en 2D, donc les tableaux 1D et 2D ne peuvent pas รชtre concatรฉnรฉs.
a1 = np.ones((2, 3), int) print(a1) # [[1 1 1] # [1 1 1]] a2 = np.full(2, 2) print(a2) # [2 2] # print(np.hstack([a1, a2])) # ValueError: all the input arrays must have same number of dimensions, but the array at index 0 has 2 dimension(s) and the array at index 1 has 1 dimension(s)
๐งโ๐ฉโ.๐โ๐ฌโ๐ญโ๐โ๐โ๐คโ() concatรจne les tableaux dans le sens de la profondeur
๐งโ๐ฉโ.๐โ๐ฌโ๐ญโ๐โ๐โ๐คโ() concatรจne les tableaux dans le sens de la profondeur.
Il est essentiellement รฉquivalent ร ๐งโ๐ฉโ.๐โ๐จโ๐งโ๐โ๐โ๐ญโ๐โ๐งโ๐โ๐ญโ๐โ() avec ๐โ๐ฑโ๐ขโ๐ฌโ=2 , mais les tableaux de 2D ou moins sont รฉtendus en 3D avant la concatรฉnation.
Les tableaux 2D sont transformรฉs de la forme (M, N) ร (M, N, 1) .
a1 = np.ones((3, 4), int) print(a1) # [[1 1 1 1] # [1 1 1 1] # [1 1 1 1]] a2 = np.full((3, 4), 2) print(a2) # [[2 2 2 2] # [2 2 2 2] # [2 2 2 2]] print(np.dstack([a1, a2])) # [[[1 2] # [1 2] # [1 2] # [1 2]] # # [[1 2] # [1 2] # [1 2] # [1 2]] # # [[1 2] # [1 2] # [1 2] # [1 2]]] print(np.dstack([a1, a2]).shape) # (3, 4, 2) print(np.dstack([a1, a2])[:, :, 0]) # [[1 1 1 1] # [1 1 1 1] # [1 1 1 1]] print(np.dstack([a1, a2])[:, :, 1]) # [[2 2 2 2] # [2 2 2 2] # [2 2 2 2]]
รquivalent ร ce qui suit ๐งโ๐ฉโ.๐โ๐จโ๐งโ๐โ๐โ๐ญโ๐โ๐งโ๐โ๐ญโ๐โ() .
print(np.concatenate([a1.reshape(3, 4, 1), a2.reshape(3, 4, 1)], 2)) # [[[1 2] # [1 2] # [1 2] # [1 2]] # # [[1 2] # [1 2] # [1 2] # [1 2]] # # [[1 2] # [1 2] # [1 2] # [1 2]]]
Les tableaux 1D sont รฉgalement รฉtendus en 3D de la forme (N, ) ร (1, N, 1) .
a1 = np.ones(3, int) print(a1) # [1 1 1] a2 = np.full(3, 2) print(a2) # [2 2 2] print(np.dstack([a1, a2])) # [[[1 2] # [1 2] # [1 2]]] print(np.dstack([a1, a2]).shape) # (1, 3, 2) print(np.dstack([a1, a2])[:, :, 0]) # [[1 1 1]] print(np.dstack([a1, a2])[:, :, 1]) # [[2 2 2]]
รquivalent ร ce qui suit ๐งโ๐ฉโ.๐โ๐จโ๐งโ๐โ๐โ๐ญโ๐โ๐งโ๐โ๐ญโ๐โ() .
print(np.concatenate([a1.reshape(1, -1, 1), a2.reshape(1, -1, 1)], 2)) # [[[1 2] # [1 2] # [1 2]]]