Question ajouter une ligne dans un pandas.DataFrame


Je comprends que les pandas est conçu pour charger pleinement peuplé DataFrame mais j'ai besoin de créer un DataFrame vide puis ajouter des lignes, une par une. Quelle est la meilleure façon de procéder ?

J'ai créé avec succès un DataFrame vide avec:

res = DataFrame(columns=('lib', 'qty1', 'qty2'))

Ensuite, je peux ajouter une nouvelle ligne et remplir un champ avec:

res = res.set_value(len(res), 'qty1', 10.0)

Cela fonctionne mais semble très étrange: - / (il échoue pour ajouter la valeur de chaîne)

Comment puis-je ajouter une nouvelle ligne à mon DataFrame (avec différents types de colonnes)?


441
2018-05-23 08:12


origine


Réponses:


Exemple chez @ Nasser's answer:

>>> import pandas as pd
>>> import numpy as np
>>> df = pd.DataFrame(columns=['lib', 'qty1', 'qty2'])
>>> for i in range(5):
>>>     df.loc[i] = [np.random.randint(-1,1) for n in range(3)]
>>>
>>> print(df)
    lib  qty1  qty2
0    0     0    -1
1   -1    -1     1
2    1    -1     1
3    0     0     0
4    1    -1    -1

[5 rows x 3 columns]

270
2017-07-22 13:10



Vous pourriez utiliser pandas.concat() ou DataFrame.append(). Pour plus de détails et des exemples, voir Fusionner, rejoindre et concaténer.


224
2018-05-23 08:14



Dans le cas où vous pouvez obtenir toutes les données pour la trame de données à l'avance, il y a une approche beaucoup plus rapide que l'ajout à une trame de données:

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

J'avais une tâche similaire pour laquelle l'ajout à une trame de données ligne par ligne prenait 30 minutes, et la création d'une trame de données à partir d'une liste de dictionnaires terminée 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)               

206
2017-07-05 20:38



Si vous connaissez le nombre d'entrées ex ante, vous devez préallouer l'espace en fournissant également l'index (en prenant l'exemple de données d'une réponse différente):

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 de vitesse

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 - à partir des commentaires - avec une taille de 6000, la différence de vitesse devient encore plus grande:

Augmenter la taille du tableau (12) et le nombre de lignes (500)   la différence de vitesse plus frappante: 313ms vs 2.29s


62
2017-07-23 14:21



Pour un ajout efficace, voir Comment ajouter une ligne supplémentaire à un dataframe de pandas et Réglage avec l'élargissement.

Ajouter des lignes à travers loc/ix sur non existant données d'index 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

51
2018-04-30 17:31



mycolumns = ['A', 'B']
df = pd.DataFrame(columns=mycolumns)
rows = [[1,2],[3,4],[5,6]]
for row in rows:
    df.loc[len(df)] = row

49
2018-06-24 21:06



Vous pouvez ajouter une seule ligne en tant que dictionnaire en utilisant le ignore_index option.

>>> f = pandas.DataFrame(data = {'Animal':['cow','horse'], 'Color':['blue', 'red']})
>>> f
  Animal Color
0    cow  blue
1  horse   red
>>> f.append({'Animal':'mouse', 'Color':'black'}, ignore_index=True)
  Animal  Color
0    cow   blue
1  horse    red
2  mouse  black

29
2018-02-23 16:43



Par souci de manière pythonique, ajoutez ici ma réponse:

res = pd.DataFrame(columns=('lib', 'qty1', 'qty2'))
res = res.append([{'qty1':10.0}], ignore_index=True)
print(res.head())

   lib  qty1  qty2
0  NaN  10.0   NaN

25
2017-08-06 05:06



Ce n'est pas une réponse à la question OP mais un exemple de jouet pour illustrer la réponse de @ShikharDua ci-dessus que j'ai trouvé très utile.

Bien que ce fragment soit trivial, dans les données réelles, j'avais des milliers de lignes et de nombreuses colonnes, et je souhaitais pouvoir regrouper par différentes colonnes et ensuite effectuer les statistiques ci-dessous pour plus d'une colonne de taget. Donc, avoir une méthode fiable pour construire la trame de données une rangée à la fois était une grande commodité. Merci @ShikharDua!

import pandas as pd 

BaseData = pd.DataFrame({ 'Customer' : ['Acme','Mega','Acme','Acme','Mega','Acme'],
                          'Territory'  : ['West','East','South','West','East','South'],
                          'Product'  : ['Econ','Luxe','Econ','Std','Std','Econ']})
BaseData

columns = ['Customer','Num Unique Products', 'List Unique Products']

rows_list=[]
for name, group in BaseData.groupby('Customer'):
    RecordtoAdd={} #initialise an empty dict 
    RecordtoAdd.update({'Customer' : name}) #
    RecordtoAdd.update({'Num Unique Products' : len(pd.unique(group['Product']))})      
    RecordtoAdd.update({'List Unique Products' : pd.unique(group['Product'])})                   

    rows_list.append(RecordtoAdd)

AnalysedData = pd.DataFrame(rows_list)

print('Base Data : \n',BaseData,'\n\n Analysed Data : \n',AnalysedData)

12
2017-07-13 09:49



Vous pouvez également créer une liste de listes et la convertir en un dataframe -

import pandas as pd

rows = []
columns = ['i','double','square']

for i in range(6):
    row = [i, i*2, i*i]
    rows.append(row)

df = pd.DataFrame(rows, columns=columns)

donnant

    je double carré
0 0 0 0
1 1 2 1
2 2 4 4
3 3 6 9
4 4 8 16
5 5 10 25

6
2017-10-13 12:16



Ça fait longtemps, mais j'ai aussi fait face au même problème. Et a trouvé ici beaucoup de réponses intéressantes. Donc, j'ai été confondu quelle méthode utiliser.

Dans le cas d'ajouter beaucoup de lignes à dataframe je suis intéressé en performance de vitesse. J'ai donc essayé 3 méthodes les plus populaires et vérifié leur vitesse.

PERFORMANCE DE VITESSE

  1. En utilisant .append (La réponse de NPE)
  2. Utiliser .loc (La réponse de fred et La réponse de FooBar)
  3. Utiliser dict et créer DataFrame à la fin (La réponse de ShikharDua)

Résultats (en secondes):

Adding    1000 rows  5000 rows   10000 rows
.append   1.04       4.84        9.56
.loc      1.16       5.59        11.50
dict      0.23       0.26        0.34

J'utilise donc l'addition à travers le dictionnaire pour moi-même.


Code:

import pandas
import numpy
import time

numOfRows = 10000
startTime = time.perf_counter()
df1 = pandas.DataFrame(numpy.random.randint(100, size=(5,5)), columns=['A', 'B', 'C', 'D', 'E'])
for i in range( 1,numOfRows):
    df1 = df1.append( dict( (a,numpy.random.randint(100)) for a in ['A','B','C','D','E']), ignore_index=True)
print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))

startTime = time.perf_counter()
df2 = pandas.DataFrame(numpy.random.randint(100, size=(5,5)), columns=['A', 'B', 'C', 'D', 'E'])
for i in range( 1,numOfRows):
    df2.loc[df2.index.max()+1]  = numpy.random.randint(100, size=(1,5))[0]
print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))

startTime = time.perf_counter()
row_list = []
for i in range (0,5):
    row_list.append(dict( (a,numpy.random.randint(100)) for a in ['A','B','C','D','E']))
for i in range( 1,numOfRows):
    dict1 = dict( (a,numpy.random.randint(100)) for a in ['A','B','C','D','E'])
    row_list.append(dict1)

df3 = pandas.DataFrame(row_list, columns=['A','B','C','D','E'])
print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))

P.S. Je crois que ma réalisation n'est pas parfaite et peut-être qu'il y a une optimisation.


6
2017-12-26 14:02