Numpy - ajouter une ligne au tableau

161

Comment ajouter des lignes à un tableau numpy?

J'ai un tableau A:

A = array([[0, 1, 2], [0, 2, 0]])

Je souhaite ajouter des lignes à ce tableau à partir d'un autre tableau X si le premier élément de chaque ligne de X remplit une condition spécifique.

Les tableaux Numpy n'ont pas de méthode «ajouter» comme celle des listes, du moins c'est ce qu'il semble.

Si A et X étaient des listes, je ferais simplement:

for i in X:
    if i[0] < 3:
        A.append(i)

Existe-t-il une manière numpythonique de faire l'équivalent?

Merci, S ;-)

Darren J. Fitzpatrick
la source

Réponses:

120

C'est quoi X? S'il s'agit d'un tableau 2D, comment pouvez-vous comparer sa ligne à un nombre i < 3:?

EDIT après le commentaire d'OP:

A = array([[0, 1, 2], [0, 2, 0]])
X = array([[0, 1, 2], [1, 2, 0], [2, 1, 2], [3, 2, 0]])

ajouter à Atoutes les lignes d' Xoù le premier élément < 3:

import numpy as np
A = np.vstack((A, X[X[:,0] < 3]))

# returns: 
array([[0, 1, 2],
       [0, 2, 0],
       [0, 1, 2],
       [1, 2, 0],
       [2, 1, 2]])
eumiro
la source
1
Désolé bon point! Supposons un tableau 2D dont le premier élément de chaque ligne doit remplir une condition. Je vais éditer cela. Merci, S ;-)
Darren J.Fitzpatrick
2
@ DarrenJ.Fitzpatrick Gardez à l'esprit qu'en faisant ce type de manipulation, vous travaillez contre le bon travail que Numpy fait en préallouant de la mémoire pour votre tableau existant A. Clairement, pour un petit problème comme dans cette réponse, ce n'est pas un problème, mais cela peut être plus inquiétant pour les données volumineuses.
dtlussier
166

Eh bien, vous pouvez le faire:

  newrow = [1,2,3]
  A = numpy.vstack([A, newrow])
jknair
la source
2
@Kris Pourquoi est-il obsolète? Je ne vois rien dans la documentation
Georgy
1
@Georgy Pour être honnête, je ne sais pas. J'étais ici à la recherche de réponses comme vous :-). Je ne me souviens plus pourquoi j'ai écrit le commentaire ci-dessus. J'ai dû voir dans la documentation son obsolète. Mais en regardant les documents maintenant ... cela ne le dit pas. Est-il possible qu'ils l'ont désapprouvé, puis ont changé d'avis à nouveau et ont décidé qu'il serait trop ennuyeux pour trop de gens de le désapprouver et de le supprimer?
Kris
32

Comme cette question remonte à 7 ans auparavant, dans la dernière version que j'utilise est numpy version 1.13, et python3, je fais la même chose avec l'ajout d'une ligne à une matrice, n'oubliez pas de mettre un double crochet au deuxième argument, sinon, cela provoquera une erreur de dimension.

Ici, j'ajoute la matrice A

1 2 3
4 5 6

avec une rangée

7 8 9

même usage dans np.r_

A= [[1, 2, 3], [4, 5, 6]]
np.append(A, [[7, 8, 9]], axis=0)

    >> array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])
#or 
np.r_[A,[[7,8,9]]]

Juste à l'intérêt de quelqu'un, si vous souhaitez ajouter une colonne,

array = np.c_[A,np.zeros(#A's row size)]

en suivant ce que nous avons fait auparavant sur la matrice A, en y ajoutant une colonne

np.c_[A, [2,8]]

>> array([[1, 2, 3, 2],
          [4, 5, 6, 8]])
Flora PJ Li
la source
11

Si aucun calcul n'est nécessaire après chaque ligne, il est beaucoup plus rapide d'ajouter des lignes en python, puis de les convertir en numpy. Voici les tests de synchronisation utilisant python 3.6 contre numpy 1.14, ajoutant 100 lignes, une à la fois:

import numpy as np 
from time import perf_counter, sleep

def time_it():
    # Compare performance of two methods for adding rows to numpy array
    py_array = [[0, 1, 2], [0, 2, 0]]
    py_row = [4, 5, 6]
    numpy_array = np.array(py_array)
    numpy_row = np.array([4,5,6])
    n_loops = 100

    start_clock = perf_counter()
    for count in range(0, n_loops):
       numpy_array = np.vstack([numpy_array, numpy_row]) # 5.8 micros
    duration = perf_counter() - start_clock
    print('numpy 1.14 takes {:.3f} micros per row'.format(duration * 1e6 / n_loops))

    start_clock = perf_counter()
    for count in range(0, n_loops):
        py_array.append(py_row) # .15 micros
    numpy_array = np.array(py_array) # 43.9 micros       
    duration = perf_counter() - start_clock
    print('python 3.6 takes {:.3f} micros per row'.format(duration * 1e6 / n_loops))
    sleep(15)

#time_it() prints:

numpy 1.14 takes 5.971 micros per row
python 3.6 takes 0.694 micros per row

Ainsi, la solution simple à la question d'origine, il y a sept ans, consiste à utiliser vstack () pour ajouter une nouvelle ligne après la conversion de la ligne en un tableau numpy. Mais une solution plus réaliste devrait tenir compte des faibles performances de vstack dans ces circonstances. Si vous n'avez pas besoin d'exécuter l'analyse des données sur le tableau après chaque ajout, il est préférable de mettre en tampon les nouvelles lignes dans une liste de lignes python (une liste de listes, vraiment), et de les ajouter en tant que groupe au tableau numpy en utilisant vstack () avant de faire une analyse de données.

rbasham
la source
10

Vous pouvez également faire ceci:

newrow = [1,2,3]
A = numpy.concatenate((A,newrow))
came
la source
2
hmmm. quand j'ai essayé cela, il a juste ajouté à la fin de A, plutôt que d'ajouter une nouvelle ligne comme OP demandé.
Todd Curry
13
probablementnp.concatenate((A,newrow), axis=0)
Konstantinos Roditakis
3
Depuis la version numpy 1.12.1(et en Python 3), il semble que tenter de concaténer un vecteur à une matrice augmente ValueError: all the input arrays must have same number of dimensions. Il semble qu'il souhaite que le vecteur soit redéfini explicitement en un vecteur de colonne ou de ligne avant de vouloir le concaténer.
MRule
3
@MRule, vous pouvez résoudre ce problème en utilisant des crochets doubles selon la réponse de @Flora PJ Li stackoverflow.com/a/47845065/1410035 . newrow = [[1,2,3]]
Tom Saleeba
5
import numpy as np
array_ = np.array([[1,2,3]])
add_row = np.array([[4,5,6]])

array_ = np.concatenate((array_, add_row), axis=0)
naman1994
la source
3

Si vous pouvez faire la construction en une seule opération, alors quelque chose comme la réponse vstack-with-fancy-indexing est une bonne approche. Mais si votre condition est plus compliquée ou si vos lignes arrivent à la volée, vous voudrez peut-être agrandir le tableau. En fait, la façon numpythonic de faire quelque chose comme ça - faire croître dynamiquement un tableau - est de développer dynamiquement une liste:

A = np.array([[1,2,3],[4,5,6]])
Alist = [r for r in A]
for i in range(100):
    newrow = np.arange(3)+i
    if i%5:
        Alist.append(newrow)
A = np.array(Alist)
del Alist

Les listes sont hautement optimisées pour ce type de modèle d'accès; vous n'avez pas d'indexation multidimensionnelle numpy pratique sous forme de liste, mais tant que vous ajoutez, il est difficile de faire mieux qu'une liste de tableaux de lignes.

user2475529
la source
3

J'utilise 'np.vstack' qui est plus rapide, EX:

import numpy as np

input_array=np.array([1,2,3])
new_row= np.array([4,5,6])

new_array=np.vstack([input_array, new_row])
RAno
la source
2

Vous pouvez utiliser numpy.append()pour ajouter une ligne à un tableau numpty et le remodeler en une matrice ultérieurement.

import numpy as np
a = np.array([1,2])
a = np.append(a, [3,4])
print a
# [1,2,3,4]
# in your example
A = [1,2]
for row in X:
    A = np.append(A, row)
Charles Chow
la source