1179 votes

Créez un cadre de données Pandas en ajoutant une ligne à la fois.

Comment puis-je créer un DataFrame puis ajouter des rangées, une par une ?

J'ai créé un DataFrame :

df = pd.DataFrame(columns=('lib', 'qty1', 'qty2'))

Je peux alors ajouter une nouvelle ligne à la fin et remplir un seul champ avec :

df = df._set_value(index=len(df), col='qty1', value=10.0)

Il ne fonctionne que pour un seul champ à la fois. Quelle est la meilleure façon d'ajouter une nouvelle ligne à la base de données ? df ?

79 votes

Notez que c'est une façon très inefficace de construire un grand DataFrame ; de nouveaux tableaux doivent être créés (en copiant les données existantes) lorsque vous ajoutez une ligne.

6 votes

@WesMcKinney : Thx, c'est vraiment bon à savoir. Est-il très rapide d'ajouter colonnes à des tables énormes ?

5 votes

Si cela est trop inefficace pour vous, vous pouvez préallouer une ligne supplémentaire et la mettre à jour ensuite.

798voto

fred Points 142

Vous pouvez utiliser df.loc[i] où la ligne avec l'indice i sera ce que vous avez spécifié dans le cadre de données.

>>> import pandas as pd
>>> from numpy.random import randint

>>> df = pd.DataFrame(columns=['lib', 'qty1', 'qty2'])
>>> for i in range(5):
>>>     df.loc[i] = ['name' + str(i)] + list(randint(10, size=2))

>>> df
     lib qty1 qty2
0  name0    3    3
1  name1    2    4
2  name2    2    8
3  name3    2    1
4  name4    9    6

34 votes

Pensez à ajouter l'index pour préallouer la mémoire (voir ma réponse).

59 votes

.loc fait référence à la colonne d'index, donc si vous travaillez avec un DataFrame préexistant dont l'index n'est pas une séquence continue d'entiers commençant par 0 (comme dans votre exemple), .loc va écraser des lignes existantes, ou insérer des lignes, ou créer des trous dans votre index. Une approche plus robuste (mais pas infaillible) pour ajouter un cadre de données existant de longueur non nulle serait la suivante : df.loc[df.index.max() + 1] = [randint(... ou en préremplissant l'index comme le suggère @FooBar.

5 votes

@hobs df.index.max() es nan lorsque le DataFrame est vide.

661voto

ShikharDua Points 356

Si vous pouvez obtenir toutes les données du cadre de données à l'avance, il existe une approche beaucoup plus rapide que l'ajout à un cadre de données :

  1. Créez une liste de dictionnaires dans laquelle chaque dictionnaire correspond à une ligne de données d'entrée.
  2. Créez un cadre de données à partir de cette liste.

J'avais une tâche similaire pour laquelle l'ajout à un cadre de données ligne par ligne prenait 30 minutes, alors que la création d'un cadre de données à partir d'une liste de dictionnaires se faisait en quelques secondes.

rows_list = []
for row in input_rows:

        dict1 = {}
        # get input row in dictionary format
        # key = col_name
        dict1.update(blah..) 

        rows_list.append(dict1)

df = pd.DataFrame(rows_list)

65 votes

J'ai commencé à faire de même pour toutes les situations où je ne peux pas obtenir toutes les données d'emblée. La différence de vitesse est étonnante.

64 votes

Copie de la documentation de pandas : It is worth noting however, that concat (and therefore append) makes a full copy of the data, and that constantly reusing this function can create a significant performance hit. If you need to use the operation over several datasets, use a list comprehension. ( pandas.pydata.org/pandas-docs/stable/ )

7 votes

Cela fonctionne très bien ! Sauf que lorsque j'ai créé le cadre de données, les noms des colonnes étaient tous dans le mauvais ordre...

323voto

NPE Points 169956

Vous pourriez utiliser pandas.concat() o DataFrame.append() . Pour plus de détails et d'exemples, voir Fusionner, joindre et concaténer .

7 votes

Bonjour, quelle est la réponse pour les méthodes utilisant append() ou concat(). J'ai le même problème, mais j'essaie toujours de le résoudre.

143 votes

C'est la bonne réponse, mais ce n'est pas une très bon réponse (presque lien seulement).

5 votes

Je pense que la réponse de @fred est plus correcte. Le problème avec cette réponse est qu'elle copie inutilement l'ensemble du DataFrame à chaque fois qu'une ligne est ajoutée. En utilisant l'option .loc mécanisme qui peut être évité, surtout si l'on fait attention.

123voto

FooBar Points 1529

Si vous connaissez le nombre d'entrées ex ante, vous devriez pré-allouer l'espace en fournissant également l'index (en reprenant l'exemple des données d'une autre réponse) :

import pandas as pd
import numpy as np
# we know we're gonna have 5 rows of data
numberOfRows = 5
# create dataframe
df = pd.DataFrame(index=np.arange(0, numberOfRows), columns=('lib', 'qty1', 'qty2') )

# now fill it up row by row
for x in np.arange(0, numberOfRows):
    #loc or iloc both work here since the index is natural numbers
    df.loc[x] = [np.random.randint(-1,1) for n in range(3)]
In[23]: df
Out[23]: 
   lib  qty1  qty2
0   -1    -1    -1
1    0     0     0
2   -1     0    -1
3    0    -1     0
4   -1     0     0

Comparaison des vitesses

In[30]: %timeit tryThis() # function wrapper for this answer
In[31]: %timeit tryOther() # function wrapper without index (see, for example, @fred)
1000 loops, best of 3: 1.23 ms per loop
100 loops, best of 3: 2.31 ms per loop

Et - d'après les commentaires - avec une taille de 6000, la différence de vitesse devient encore plus grande :

L'augmentation de la taille du tableau (12) et du nombre de rangées (500) rend la différence de vitesse est plus frappante : 313 ms contre 2,29 s.

4 votes

Excellente réponse. Cela devrait être la norme afin que l'espace de la rangée ne soit pas alloué de manière incrémentielle.

9 votes

En augmentant la taille du tableau (12) et le nombre de lignes (500), la différence de vitesse est plus frappante : 313 ms contre 2,29 s.

75voto

Nasser Al-Wohaibi Points 578

Pour un ajout efficace, voir Comment ajouter une ligne supplémentaire à un cadre de données pandas ? y Réglage avec l'élargissement .

Ajouter des lignes par le biais de loc/ix en non existant données de l'indice clé. Par exemple :

In [1]: se = pd.Series([1,2,3])

In [2]: se
Out[2]:
0    1
1    2
2    3
dtype: int64

In [3]: se[5] = 5.

In [4]: se
Out[4]:
0    1.0
1    2.0
2    3.0
5    5.0
dtype: float64

Ou :

In [1]: dfi = pd.DataFrame(np.arange(6).reshape(3,2),
   .....:                 columns=['A','B'])
   .....:

In [2]: dfi
Out[2]:
   A  B
0  0  1
1  2  3
2  4  5

In [3]: dfi.loc[:,'C'] = dfi.loc[:,'A']

In [4]: dfi
Out[4]:
   A  B  C
0  0  1  0
1  2  3  2
2  4  5  4
In [5]: dfi.loc[3] = 5

In [6]: dfi
Out[6]:
   A  B  C
0  0  1  0
1  2  3  2
2  4  5  4
3  5  5  5

1 votes

Les utilisateurs ont demandé la mise en œuvre (ajouter une nouvelle ligne). Ici nous voyons comment ajouter une ligne dans un index défini ou ajouter une colonne.

1 votes

Avez-vous des points de repère sur la façon dont cela fonctionne par rapport à la méthode de la dictée ?

0 votes

Cette méthode n'est pas efficace car elle copie l'intégralité du DataFrame.

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