Je commence à partir du pandas DataFrame docs ici: http://pandas.pydata.org/pandas-docs/stable/dsintro.html
Je voudrais remplir de manière itérative le DataFrame avec des valeurs dans un type de calcul de série chronologique. Donc, fondamentalement, j'aimerais initialiser le DataFrame avec les colonnes A, B et les lignes d'horodatage, toutes les 0 ou toutes les NaN.
J'ajoutais ensuite les valeurs initiales et examinais ces données en calculant la nouvelle ligne à partir de la ligne précédente, par exemple, row[A][t] = row[A][t-1]+1
ou plus.
J'utilise actuellement le code ci-dessous, mais j'estime que c'est un peu moche et qu'il doit y avoir un moyen de faire cela directement avec un DataFrame, ou juste une meilleure façon en général. Note: J'utilise Python 2.7.
import datetime as dt
import pandas as pd
import scipy as s
if __== '__main__':
base = dt.datetime.today().date()
dates = [ base - dt.timedelta(days=x) for x in range(0,10) ]
dates.sort()
valdict = {}
symbols = ['A','B', 'C']
for symb in symbols:
valdict[symb] = pd.Series( s.zeros( len(dates)), dates )
for thedate in dates:
if thedate > dates[0]:
for symb in valdict:
valdict[symb][thedate] = 1+valdict[symb][thedate - dt.timedelta(days=1)]
print valdict
Voici quelques suggestions:
Utilisez date_range
pour l'index:
_import datetime
import pandas as pd
import numpy as np
todays_date = datetime.datetime.now().date()
index = pd.date_range(todays_date-datetime.timedelta(10), periods=10, freq='D')
columns = ['A','B', 'C']
_
Remarque: nous pourrions créer un DataFrame vide (avec NaN
s) simplement en écrivant:
_df_ = pd.DataFrame(index=index, columns=columns)
df_ = df_.fillna(0) # with 0s rather than NaNs
_
Pour effectuer ces types de calculs pour les données, utilisez un tableau numpy:
_data = np.array([np.arange(10)]*3).T
_
Nous pouvons donc créer le DataFrame:
_In [10]: df = pd.DataFrame(data, index=index, columns=columns)
In [11]: df
Out[11]:
A B C
2012-11-29 0 0 0
2012-11-30 1 1 1
2012-12-01 2 2 2
2012-12-02 3 3 3
2012-12-03 4 4 4
2012-12-04 5 5 5
2012-12-05 6 6 6
2012-12-06 7 7 7
2012-12-07 8 8 8
2012-12-08 9 9 9
_
Si vous souhaitez simplement créer un cadre de données vide et le remplir ultérieurement avec des cadres de données entrants, essayez ceci:
Dans cet exemple, j'utilise this pandas doc pour créer un nouveau bloc de données, puis append pour écrire dans newDF avec les données de oldDF.
Regardez ça
newDF = pd.DataFrame() #creates a new dataframe that's empty
newDF = newDF.append(oldDF, ignore_index = True) # ignoring index is optional
# try printing some data from newDF
print newDF.head() #again optional
Si vous souhaitez que vos noms de colonne soient en place dès le début, utilisez cette approche:
import pandas as pd
col_names = ['A', 'B', 'C']
my_df = pd.DataFrame(columns = col_names)
my_df
Si vous souhaitez ajouter un enregistrement à la structure de données, il est préférable d'utiliser:
my_df.loc[len(my_df)] = [2, 4, 5]
Vous voudrez peut-être aussi passer un dictionnaire:
my_dic = {'A':2, 'B':4, 'C':5}
my_df.loc[len(my_df)] = my_dic
Toutefois, si vous souhaitez ajouter un autre cadre de données à my_df, procédez comme suit:
col_names = ['A', 'B', 'C']
my_df2 = pd.DataFrame(columns = col_names)
my_df = my_df.append(my_df2)
Si vous ajoutez des lignes dans une boucle, tenez compte des problèmes de performances:
Pour environ 1000 premiers enregistrements, les performances de "my_df.loc" sont meilleures, mais elles deviennent de plus en plus lentes en augmentant le nombre d’enregistrements dans la boucle.
Si vous envisagez de faire le thin dans une grande boucle (disons 10M enregistrements environ):
Vous feriez mieux d’utiliser un mélange de ces deux éléments; remplissez une image de données avec iloc jusqu'à ce que la taille atteigne environ 1 000, puis ajoutez-la à l'image d'origine et videz l'image de travail temporaire. Cela augmenterait vos performances d'environ 10 fois.
La plupart des réponses ici vous diront comment créer et remplir un DataFrame vide, mais personne ne vous dira que c'est une mauvaise chose à faire.
Voici mon conseil: Attendez d’être sûr de disposer de toutes les données nécessaires pour travailler. Utilisez une liste pour collecter vos données, puis initialisez un DataFrame lorsque vous êtes prêt.
data = []
for a, b, c in some_function_that_yields_data():
data.append([a, b, c])
df = pd.DataFrame(data, columns=['A', 'B', 'C'])
Il est toujours moins coûteux d’ajouter à une liste et de créer un DataFrame en une fois que de créer un DataFrame vide (ou l’un des NaNs) et y ajouter encore et encore. Les listes utilisent également moins de mémoire et constituent une structure de données beaucoup plus légère pour travailler avec , ajouter et supprimer (si nécessaire).
L’autre avantage de cette méthode est que dtypes
sont automatiquement déduits (plutôt que d’attribuer object
à tous).
Le dernier avantage est que une RangeIndex
est automatiquement créée pour vos données , c’est donc une chose de moins à craindre (regardez les méthodes pauvres append
et loc
ci-dessous, vous verrez les éléments dans les deux nécessitant une gestion appropriée de l'index).
append
ou concat
dans une boucleVoici la plus grosse erreur que j'ai vue des débutants:
df = pd.DataFrame(columns=['A', 'B', 'C'])
for a, b, c in some_function_that_yields_data():
df = df.append({'A': i, 'B': b, 'C': c}, ignore_index=True) # yuck
# or similarly,
# df = pd.concat([df, pd.Series({'A': i, 'B': b, 'C': c})], ignore_index=True)
La mémoire est réaffectée à chaque opération append
ou concat
. Coupler ceci avec une boucle et vous aurez une opération de complexité quadratique . À partir de la df.append
page doc :
L'ajout itératif de lignes à un DataFrame peut nécessiter plus de calculs qu'une simple concaténation. Une meilleure solution consiste à ajouter ces lignes à une liste, puis à concaténer la liste avec le DataFrame d'origine en une seule fois.
L'autre erreur associée à df.append
est que les utilisateurs ont tendance à oublier append n'est pas une fonction in-situ , le résultat doit donc être attribué à nouveau. . Vous devez également vous soucier des types de données:
df = pd.DataFrame(columns=['A', 'B', 'C'])
df = df.append({'A': 1, 'B': 12.3, 'C': 'xyz'}, ignore_index=True)
df.dtypes
A object # yuck!
B float64
C object
dtype: object
Traiter avec des colonnes d'objet n'est jamais une bonne chose, car pandas ne peut pas vectoriser les opérations sur ces colonnes. Vous devrez le faire pour résoudre ce problème:
df.infer_objects().dtypes
A int64
B float64
C object
dtype: object
loc
dans une boucleJ'ai aussi vu loc
utilisé pour ajouter à un DataFrame créé vide:
df = pd.DataFrame(columns=['A', 'B', 'C'])
for a, b, c in some_function_that_yields_data():
df.loc[len(df)] = [a, b, c]
Comme auparavant, vous n'avez pas pré-alloué la quantité de mémoire dont vous avez besoin à chaque fois. Ainsi , la mémoire est redéveloppée chaque fois que vous créez une nouvelle ligne . C'est aussi grave que append
, et encore plus moche.
Et puis, il y a la création d'un DataFrame of NaNs, et toutes les mises en garde associées.
df = pd.DataFrame(columns=['A', 'B', 'C'], index=range(5))
df
A B C
0 NaN NaN NaN
1 NaN NaN NaN
2 NaN NaN NaN
3 NaN NaN NaN
4 NaN NaN NaN
Il crée un DataFrame de colonnes d'objet, comme les autres.
df.dtypes
A object # you DON'T want this
B object
C object
dtype: object
Ajouter a toujours tous les problèmes que les méthodes ci-dessus.
for i, (a, b, c) in enumerate(some_function_that_yields_data()):
df.iloc[i] = [a, b, c]
La synchronisation de ces méthodes est le moyen le plus rapide de voir à quel point elles diffèrent en termes de mémoire et d’utilité.