Comment ajouter une nouvelle ligne à un tableau numpy vide

158

En utilisant des tableaux Python standard, je peux faire ce qui suit:

arr = []
arr.append([1,2,3])
arr.append([4,5,6])
# arr is now [[1,2,3],[4,5,6]]

Cependant, je ne peux pas faire la même chose avec numpy. Par exemple:

arr = np.array([])
arr = np.append(arr, np.array([1,2,3]))
arr = np.append(arr, np.array([4,5,6]))
# arr is now [1,2,3,4,5,6]

J'ai également examiné vstack, mais lorsque j'utilise vstacksur un tableau vide, j'obtiens:

ValueError: all the input array dimensions except for the concatenation axis must match exactly

Alors, comment puis-je ajouter une nouvelle ligne à un tableau vide dans numpy?

Tony Stark
la source
1
S'il est vide, pourquoi s'embêter? Commencez simplement à partir d'un tableau contenant uniquement la première ligne.
jonrsharpe
10
Je veux juste savoir s'il est possible d'ajouter à un tableau numpy vide. Parfois, il est plus propre d'écrire du code comme celui-ci car les opérations d'ajout sont dans une boucle.
Tony Stark
5
Compte tenu du fonctionnement des tableaux numpy, il est préférable de créer un tableau vide que de mettre les données, par exemple Voir stackoverflow.com/questions/568962/…
jonrsharpe

Réponses:

228

La façon de «démarrer» le tableau que vous souhaitez est:

arr = np.empty((0,3), int)

Ce qui est un tableau vide mais il a la dimensionnalité appropriée.

>>> arr
array([], shape=(0, 3), dtype=int64)

Assurez-vous ensuite d'ajouter le long de l'axe 0:

arr = np.append(arr, np.array([[1,2,3]]), axis=0)
arr = np.append(arr, np.array([[4,5,6]]), axis=0)

Mais, @jonrsharpe a raison. En fait, si vous allez ajouter dans une boucle, il serait beaucoup plus rapide d'ajouter à une liste comme dans votre premier exemple, puis de convertir en un tableau numpy à la fin, car vous n'utilisez vraiment pas numpy comme prévu pendant la boucle:

In [210]: %%timeit
   .....: l = []
   .....: for i in xrange(1000):
   .....:     l.append([3*i+1,3*i+2,3*i+3])
   .....: l = np.asarray(l)
   .....: 
1000 loops, best of 3: 1.18 ms per loop

In [211]: %%timeit
   .....: a = np.empty((0,3), int)
   .....: for i in xrange(1000):
   .....:     a = np.append(a, 3*i+np.array([[1,2,3]]), 0)
   .....: 
100 loops, best of 3: 18.5 ms per loop

In [214]: np.allclose(a, l)
Out[214]: True

La façon numpythonique de le faire dépend de votre application, mais ce serait plutôt comme:

In [220]: timeit n = np.arange(1,3001).reshape(1000,3)
100000 loops, best of 3: 5.93 µs per loop

In [221]: np.allclose(a, n)
Out[221]: True
Askewchan
la source
et si je dois faire cela 10 ^ 5 ou 10 ^ 6 fois? il semble qu'aucune de ces méthodes ne tiendra. toute suggestion?
Rho Phi du
@Roberto, il existe généralement un moyen de déterminer à l'avance la taille ou la forme (à tout le moins, des valeurs seraient préférables) du tableau. Pensez-vous pouvoir faire ça? L'ajout devrait vraiment être une opération une ou deux fois.
askewchan
parfois vous ne pouvez pas deviner les dimensions, c'est la vie. Cependant, vous pouvez allouer un tableau suffisamment grand et donner des valeurs à ses vues. Je n'aime pas ça cependant, car il y a des valeurs indésirables qu'il faut trouver un moyen de "masquer". Cette idée de masquer ne correspond vraiment pas à mon goût.
Rho Phi
Pas besoin de masquer, il suffit de trancher! a = a[:N] Bien que je crois fermement que vous devriez trouver un moyen de le vectoriser (postez une nouvelle question avec vos détails si vous avez besoin d'aide) ou utilisez simplement des listes jusqu'à ce que la boucle soit terminée.
askewchan
29

Voici ma solution:

arr = []
arr.append([1,2,3])
arr.append([4,5,6])
np_arr = np.array(arr)
just4fun
la source
Le tableau résultant a un type d'objet, ce qui n'est pas acceptable dans certains cas
zer0fool
26

Dans ce cas, vous pouvez utiliser les fonctions np.hstack et np.vstack

arr = np.array([])
arr = np.hstack((arr, np.array([1,2,3])))
# arr is now [1,2,3]

arr = np.vstack((arr, np.array([4,5,6])))
# arr is now [[1,2,3],[4,5,6]]

Vous pouvez également utiliser la fonction np.concatenate.

À votre santé

mrcl
la source
7
Ne fonctionnera pas si le deuxième tableau a une dimension> = 2 comme ceux ((2, 2)). Il me semble qu'il n'y a aucun moyen d'éviter les cas limites si vous construisez des tableaux à partir de vides par concaténation.
Taozi
Ce n'est pas une bonne solution car il faut vérifier la dimension à chaque fois.
SKR
1

en utilisant une définition dtype personnalisée, ce qui a fonctionné pour moi était:

import numpy

# define custom dtype
type1 = numpy.dtype([('freq', numpy.float64, 1), ('amplitude', numpy.float64, 1)])
# declare empty array, zero rows but one column
arr = numpy.empty([0,1],dtype=type1)
# store row data, maybe inside a loop
row = numpy.array([(0.0001, 0.002)], dtype=type1)
# append row to the main array
arr = numpy.row_stack((arr, row))
# print values stored in the row 0
print float(arr[0]['freq'])
print float(arr[0]['amplitude'])
boclodoa
la source
1

En cas d'ajout de nouvelles lignes pour le tableau en boucle, assignez le tableau directement pour la première fois en boucle au lieu d'initialiser un tableau vide.

for i in range(0,len(0,100)):
    SOMECALCULATEDARRAY = .......
    if(i==0):
        finalArrayCollection = SOMECALCULATEDARRAY
    else:
        finalArrayCollection = np.vstack(finalArrayCollection,SOMECALCULATEDARRAY)

Ceci est principalement utile lorsque la forme du tableau est inconnue

Rajesh_Saladi
la source
0

Je veux faire une boucle for, mais avec la méthode askewchan cela ne fonctionne pas bien, donc je l'ai modifié.

x=np.empty((0,3))
y=np.array([1 2 3])
for i in ...
x = vstack((x,y))
Qingdong Wang
la source