web-dev-qa-db-fra.com

Comment ajouter des lignes dans un pandas dataframe dans une boucle for?

J'ai le suivant pour la boucle:

for i in links:
     data = urllib2.urlopen(str(i)).read()
     data = json.loads(data)
     data = pd.DataFrame(data.items())
     data = data.transpose()
     data.columns = data.iloc[0]
     data = data.drop(data.index[[0]])

Chaque dataframe ainsi créé a la plupart des colonnes en commun avec les autres mais pas toutes. De plus, ils n’ont tous qu’une rangée. Ce que je dois faire, c'est ajouter à la trame de données toutes les colonnes distinctes et chaque ligne de chaque trame de données produite par la boucle for

J'ai essayé pandas concaténer ou similaire, mais rien ne semblait fonctionner. Une idée? Merci.

48
Blue Moon

Supposons que vos données ressemblent à ceci:

import pandas as pd
import numpy as np

np.random.seed(2015)
df = pd.DataFrame([])
for i in range(5):
    data = dict(Zip(np.random.choice(10, replace=False, size=5),
                    np.random.randint(10, size=5)))
    data = pd.DataFrame(data.items())
    data = data.transpose()
    data.columns = data.iloc[0]
    data = data.drop(data.index[[0]])
    df = df.append(data)
print('{}\n'.format(df))
# 0   0   1   2   3   4   5   6   7   8   9
# 1   6 NaN NaN   8   5 NaN NaN   7   0 NaN
# 1 NaN   9   6 NaN   2 NaN   1 NaN NaN   2
# 1 NaN   2   2   1   2 NaN   1 NaN NaN NaN
# 1   6 NaN   6 NaN   4   4   0 NaN NaN NaN
# 1 NaN   9 NaN   9 NaN   7   1   9 NaN NaN

Ensuite, il pourrait être remplacé par

np.random.seed(2015)
data = []
for i in range(5):
    data.append(dict(Zip(np.random.choice(10, replace=False, size=5),
                         np.random.randint(10, size=5))))
df = pd.DataFrame(data)
print(df)

En d'autres termes, ne formez pas un nouveau DataFrame pour chaque ligne. Au lieu de cela, rassemblez toutes les données dans une liste de plans, puis appelez df = pd.DataFrame(data) une fois à la fin, en dehors de la boucle.

Chaque appel à df.append nécessite d'allouer de l'espace pour un nouveau DataFrame avec une ligne supplémentaire, de copier toutes les données du DataFrame d'origine dans le nouveau DataFrame, puis de les copier dans la nouvelle ligne. Toute cette allocation et cette copie rendent l'appel de df.append dans une boucle très inefficace. Le coût en temps de la copie croît quadratiquement avec le nombre de lignes. Non seulement le code call-DataFrame-once est plus facile à écrire, mais ses performances seront bien meilleures: le coût en temps de la copie augmente de manière linéaire avec le nombre de lignes.

52
unutbu

Vous pouvez ajouter des lignes dans une boucle pour deux raisons: 1. ajouter à un fichier DF existant et 2. créer un nouveau fichier DF.

pour créer un nouveau fichier DF, je pense qu'il est bien documenté que vous devez créer vos données sous forme de liste, puis créer le bloc de données:

cols = ['c1', 'c2', 'c3']
lst = []
for a in range(2):
    lst.append([1, 2, 3])
df1 = pd.DataFrame(lst, columns=cols)
df1
Out[3]: 
   c1  c2  c3
0   1   2   3
1   1   2   3

OU, créez le dataframe avec un index puis ajoutez-le

cols = ['c1', 'c2', 'c3']
df2 = pd.DataFrame(columns=cols, index=range(2))
for a in range(2):
    df2.loc[a].c1 = 4
    df2.loc[a].c2 = 5
    df2.loc[a].c3 = 6
df2
Out[4]: 
  c1 c2 c3
0  4  5  6
1  4  5  6

Si vous souhaitez ajouter des éléments à une structure de données existante, vous pouvez utiliser l'une des méthodes ci-dessus, puis ajouter les df ensemble (avec ou sans l'index):

df3 = df2.append(df1, ignore_index=True)
df3
Out[6]: 
  c1 c2 c3
0  4  5  6
1  4  5  6
2  1  2  3
3  1  2  3

Ou, vous pouvez également créer une liste d'entrées de dictionnaire et les ajouter comme dans la réponse ci-dessus.

lst_dict = []
for a in range(2):
    lst_dict.append({'c1':2, 'c2':2, 'c3': 3})
df4 = df1.append(lst_dict)
df4
Out[7]: 
   c1  c2  c3
0   1   2   3
1   1   2   3
0   2   2   3
1   2   2   3

Utiliser le dict (Zip (cols, vals)))

lst_dict = []
for a in range(2):
    vals = [7, 8, 9]
    lst_dict.append(dict(Zip(cols, vals)))
df5 = df1.append(lst_dict)
49
kztd

J'ai créé un cadre de données dans une boucle for à l'aide d'un cadre de données vide temporaire. Parce que pour chaque itération de for, un nouveau cadre de données sera créé, écrasant ainsi le contenu de l'itération précédente.

Par conséquent, je dois déplacer le contenu du bloc de données vers le bloc de données vide déjà créé. C'est aussi simple que ça. Nous avons juste besoin d'utiliser la fonction .append comme indiqué ci-dessous:

temp_df = pd.DataFrame() #Temporary empty dataframe
for sent in Sentences:
    New_df = pd.DataFrame({'words': sent.words}) #Creates a new dataframe and contains tokenized words of input sentences
    temp_df = temp_df.append(New_df, ignore_index=True) #Moving the contents of newly created dataframe to the temporary dataframe

En dehors de la boucle for, vous pouvez copier le contenu du bloc de données temporaire dans le bloc de données maître, puis supprimer le bloc de données temporaire si vous n'en avez pas besoin.

4
JKC

Un moyen plus compact et efficace serait peut-être:

cols = ['frame', 'count']
N = 4
dat = pd.DataFrame(columns = cols)
for i in range(N):

    dat = dat.append({'frame': str(i), 'count':i},ignore_index=True)

la sortie serait:

>>> dat
   frame count
0     0     0
1     1     1
2     2     2
3     3     3
1
Ayanava Sarkar