366 votes

Concaténation de deux tableaux NumPy unidimensionnels

J'ai deux tableaux unidimensionnels simples dans l'application NumPy . Je devrais être capable de les concaténer en utilisant numpy.concatenate . Mais j'obtiens cette erreur pour le code ci-dessous :

TypeError : seuls les tableaux de longueur 1 peuvent être convertis en scalaires Python

Code

import numpy
a = numpy.array([1, 2, 3])
b = numpy.array([5, 6])
numpy.concatenate(a, b)

Pourquoi ?

3 votes

Si vous voulez les concaténer (en un seul tableau) le long de un axe, utilisez np.concatenat(..., axis) . Si vous voulez les empiler verticalement, utilisez np.vstack . Si vous voulez les empiler (en plusieurs tableaux) horizontalement, utilisez np.hstack . (Si vous voulez les empiler en profondeur, c'est-à-dire dans la troisième dimension, utilisez np.dstack ). Notez que ces dernières sont similaires à celles de pandas pd.concat

488voto

Winston Ewert Points 17746

La ligne devrait être :

numpy.concatenate([a,b])

Les tableaux que vous voulez concaténer doivent être passés en tant que séquence, et non comme des arguments séparés.

Desde el Documentation NumPy :

numpy.concatenate((a1, a2, ...), axis=0)

Joindre une séquence de tableaux ensemble.

Il essayait d'interpréter votre b comme paramètre d'axe, c'est pourquoi il s'est plaint de ne pas pouvoir le convertir en scalaire.

3 votes

Merci ! Je suis juste curieux - quelle est la logique derrière tout cela ?

9 votes

@user391339, et si vous vouliez concaténer trois tableaux ? La fonction est plus utile pour prendre une séquence que si elle prenait juste deux tableaux.

0 votes

@WinstonEwert En supposant que le problème n'est pas qu'il est codé en dur avec deux arguments, vous pourriez l'utiliser comme suit numpy.concatenate(a1, a2, a3) o numpy.concatenate(*[a1, a2, a3]) si vous préférez. Python est suffisamment fluide pour que la différence finisse par être plus cosmétique que substantielle, mais c'est une bonne chose lorsque l'API est cohérente (par exemple, si toutes les fonctions numpy qui prennent des listes d'arguments de longueur variable nécessitent des séquences explicites).

74voto

Nico Points 893

Il existe plusieurs possibilités pour concaténer des tableaux 1D, par exemple,

numpy.r_[a, a],
numpy.stack([a, a]).reshape(-1),
numpy.hstack([a, a]),
numpy.concatenate([a, a])

Toutes ces options sont aussi rapides pour les grandes matrices que pour les petites, concatenate a un léger bord :

enter image description here

La parcelle a été créée avec perfplot :

import numpy
import perfplot

perfplot.show(
    setup=lambda n: numpy.random.rand(n),
    kernels=[
        lambda a: numpy.r_[a, a],
        lambda a: numpy.stack([a, a]).reshape(-1),
        lambda a: numpy.hstack([a, a]),
        lambda a: numpy.concatenate([a, a]),
    ],
    labels=["r_", "stack+reshape", "hstack", "concatenate"],
    n_range=[2 ** k for k in range(19)],
    xlabel="len(a)",
)

17 votes

Les alternatives utilisent toutes np.concatenate . Ils ne font que masser la liste d'entrée de diverses manières à l'avance. np.stack par exemple, ajoute une dimension supplémentaire à tous les tableaux d'entrée. Regardez leur code source. Seulement concatenate est compilé.

2 votes

Juste pour ajouter au commentaire de @hpaulj - les temps convergent tous lorsque la taille des tableaux augmente parce que la fonction np.concatenate fait des copies des entrées. Ce coût en mémoire et en temps l'emporte alors sur le temps passé à "masser" les entrées.

0 votes

Merci ! J'ai utilisé votre code pour vérifier également l'influence du nombre de tableaux (de taille 100) et j'ai obtenu des résultats similaires : i.stack.imgur.com/w6ojK.png

38voto

Gabe Points 49718

Le premier paramètre de concatenate devrait lui-même être un séquence de tableaux pour concaténer :

numpy.concatenate((a,b)) # Note the extra parentheses.

14voto

Ergodicity Points 294

Une alternative est d'utiliser la forme courte de "concatenate" qui est soit "r_[...]" soit "c_[...]" comme indiqué dans l'exemple de code ci-dessous (voir http://wiki.scipy.org/NumPy_for_Matlab_Users pour de plus amples informations) :

%pylab
vector_a = r_[0.:10.] #short form of "arange"
vector_b = array([1,1,1,1])
vector_c = r_[vector_a,vector_b]
print vector_a
print vector_b
print vector_c, '\n\n'

a = ones((3,4))*4
print a, '\n'
c = array([1,1,1])
b = c_[a,c]
print b, '\n\n'

a = ones((4,3))*4
print a, '\n'
c = array([[1,1,1]])
b = r_[a,c]
print b

print type(vector_b)

Ce qui a pour conséquence :

[ 0.  1.  2.  3.  4.  5.  6.  7.  8.  9.]
[1 1 1 1]
[ 0.  1.  2.  3.  4.  5.  6.  7.  8.  9.  1.  1.  1.  1.] 

[[ 4.  4.  4.  4.]
 [ 4.  4.  4.  4.]
 [ 4.  4.  4.  4.]] 

[[ 4.  4.  4.  4.  1.]
 [ 4.  4.  4.  4.  1.]
 [ 4.  4.  4.  4.  1.]] 

[[ 4.  4.  4.]
 [ 4.  4.  4.]
 [ 4.  4.  4.]
 [ 4.  4.  4.]] 

[[ 4.  4.  4.]
 [ 4.  4.  4.]
 [ 4.  4.  4.]
 [ 4.  4.  4.]
 [ 1.  1.  1.]]

2 votes

vector_b = [1,1,1,1] #short form of "array" vector_b sera un type de liste Python standard. Numpy est cependant assez bon pour accepter des séquences au lieu de forcer toutes les entrées à être des types numpy.array.

2 votes

Vous avez raison - je me suis trompé. J'ai corrigé mon code source ainsi que le résultat.

2voto

mario23 Points 322

Voici d'autres approches pour y parvenir en utilisant numpy.ravel() , numpy.array() en utilisant le fait que les tableaux 1D peuvent être décomposés en éléments simples :

# we'll utilize the concept of unpacking
In [15]: (*a, *b)
Out[15]: (1, 2, 3, 5, 6)

# using `numpy.ravel()`
In [14]: np.ravel((*a, *b))
Out[14]: array([1, 2, 3, 5, 6])

# wrap the unpacked elements in `numpy.array()`
In [16]: np.array((*a, *b))
Out[16]: array([1, 2, 3, 5, 6])

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X