web-dev-qa-db-fra.com

Ajouter une ligne à pandas DataFrame

Je comprends que pandas est conçu pour charger DataFrame complètement peuplé, mais il me faut 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 une valeur de chaîne)

Comment puis-je ajouter une nouvelle ligne à mon DataFrame (avec un type de colonne différent)?

672
PhE
>>> 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
433
fred

Si vous pouvez obtenir toutes les données pour le bloc de données au début, il existe une approche beaucoup plus rapide que l'ajout d'un bloc 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 bloc 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 et la création d'un cadre 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)               
351
ShikharDua

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

259
NPE

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:

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

91
FooBar

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

Dans le cas de l'ajout de nombreuses lignes à la structure de données, je m'intéressais aux performances de vitesse . J'ai donc essayé 4 méthodes les plus populaires et vérifié leur vitesse.

MIS À JOUR EN 2019 à l'aide de nouvelles versions de packages. Également mis à jour après @ commentaire de FooBar

PERFORMANCE DE VITESSE

  1. Utilisation de .append ( réponse de NPE )
  2. Utiliser .loc ( réponse de fred )
  3. Utilisation de .loc avec préallocation ( réponse de FooBar )
  4. Utiliser dict et créer DataFrame à la fin ( réponse de ShikharDua )

Résultats (en secondes):

|------------|-------------|-------------|-------------|
|  Approach  |  1000 rows  |  5000 rows  | 10 000 rows |
|------------|-------------|-------------|-------------|
| .append    |    0.69     |    3.39     |    6.78     |
|------------|-------------|-------------|-------------|
| .loc w/o   |    0.74     |    3.90     |    8.35     |
| prealloc   |             |             |             |
|------------|-------------|-------------|-------------|
| .loc with  |    0.24     |    2.58     |    8.70     |
| prealloc   |             |             |             |
|------------|-------------|-------------|-------------|
|  dict      |    0.012    |   0.046     |   0.084     |
|------------|-------------|-------------|-------------|

Merci également à @ krassowski pour un commentaire utile - J'ai mis à jour le code.

Donc, j'utilise l'addition par le dictionnaire pour moi-même.


Code:

import pandas as pd
import numpy as np
import time

del df1, df2, df3, df4
numOfRows = 1000
# append
startTime = time.perf_counter()
df1 = pd.DataFrame(np.random.randint(100, size=(5,5)), columns=['A', 'B', 'C', 'D', 'E'])
for i in range( 1,numOfRows-4):
    df1 = df1.append( dict( (a,np.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))
print(df1.shape)

# .loc w/o prealloc
startTime = time.perf_counter()
df2 = pd.DataFrame(np.random.randint(100, size=(5,5)), columns=['A', 'B', 'C', 'D', 'E'])
for i in range( 1,numOfRows):
    df2.loc[i]  = np.random.randint(100, size=(1,5))[0]
print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))
print(df2.shape)

# .loc with prealloc
df3 = pd.DataFrame(index=np.arange(0, numOfRows), columns=['A', 'B', 'C', 'D', 'E'] )
startTime = time.perf_counter()
for i in range( 1,numOfRows):
    df3.loc[i]  = np.random.randint(100, size=(1,5))[0]
print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))
print(df3.shape)

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

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

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

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

Pour des ajouts efficaces, voir Comment ajouter une ligne supplémentaire à un pandas dataframe et Définition avec agrandissement .

Ajoutez des lignes via loc/ix sur des données d'index de clé non existantes . 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
65
Nasser Al-Wohaibi

Vous pouvez ajouter une seule ligne sous forme de dictionnaire à l'aide de l'option ignore_index.

>>> 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
53
W.P. McNeill

Par souci de la façon 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
38
hkyi

Vous pouvez également créer une liste de listes et la convertir en une base de données -

import pandas as pd

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

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

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

donnant

 i 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 
15
Brian Burns

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

Bien que ce fragment soit trivial, dans les données réelles, j'avais 1 000 rangées et de nombreuses colonnes et je souhaitais pouvoir regrouper différentes colonnes, puis effectuer les statistiques ci-dessous pour plus d'une colonne de taget. Il était donc très pratique d’avoir une méthode fiable pour construire le bloc de données ligne par ligne. 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)
13
user3250815

Compris de manière simple et agréable:

>>> df
     A  B  C
one  1  2  3
>>> df.loc["two"] = [4,5,6]
>>> df
     A  B  C
one  1  2  3
two  4  5  6
10
Qinsi

Voici le moyen d'ajouter/ajouter une ligne dans pandas DataFrame

def add_row(df, row):
    df.loc[-1] = row
    df.index = df.index + 1  
    return df.sort_index()

add_row(df, [1,2,3]) 

Il peut être utilisé pour insérer/ajouter une ligne dans un champ vide ou peuplé pandas DataFrame

6
Shivam Agrawal

Créez un nouvel enregistrement (trame de données) et ajoutez-le à old_data_frame.
liste de contrôle de valeurs et des colonnes noms correspondants pour créer un new_record (data_frame)

new_record = pd.DataFrame([[0,'abcd',0,1,123]],columns=['a','b','c','d','e'])

old_data_frame = pd.concat([old_data_frame,new_record])
5
Jack Daniel

Une autre façon de le faire (probablement pas très performant):

# add a row
def add_row(df, row):
    colnames = list(df.columns)
    ncol = len(colnames)
    assert ncol == len(row), "Length of row must be the same as width of DataFrame: %s" % row
    return df.append(pd.DataFrame([row], columns=colnames))

Vous pouvez également améliorer la classe DataFrame comme ceci:

import pandas as pd
def add_row(self, row):
    self.loc[len(self.index)] = row
pd.DataFrame.add_row = add_row
3
qed

Faites simple. En prenant la liste comme entrée qui sera ajoutée comme ligne dans le cadre de données: -

import pandas as pd  
res = pd.DataFrame(columns=('lib', 'qty1', 'qty2'))  
for i in range(5):  
    res_list = list(map(int, input().split()))  
    res = res.append(pd.Series(res_list,index=['lib','qty1','qty2']), ignore_index=True)
1
Vineet Jain
import pandas as pd 
t1=pd.DataFrame()
for i in range(len(the number of rows)):
    #add rows as columns
    t1[i]=list(rows)
t1=t1.transpose()
t1.columns=list(columns)
0
Vicky

Nous voyons souvent la construction df.loc[subscript] = … à attribuer à une ligne DataFrame. Mikhail_Sam posted benchmarks contenant, entre autres, cette construction ainsi que la méthode utilisant dict et crée DataFrame à la fin . Il a trouvé que ce dernier était de loin le plus rapide. Mais si nous remplaçons le df3.loc[i] = … (avec DataFrame préalloué) dans son code avec df3.values[i] = …, le résultat change de manière significative, en ce sens que cette méthode est similaire à celle utilisant dict. Nous devrions donc prendre plus souvent en considération l'utilisation de df.values[subscript] = …. Cependant, notez que .values prend un indice de base zéro, qui peut être différent de DataFrame.index.

0
Armali