web-dev-qa-db-fra.com

Créer un Pandas _ DataFrame vide, puis le remplir?

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
343
Matthias Kauer

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 NaNs) 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
_
266
Andy Hayden

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 je dois continuer à ajouter de nouvelles données à ce newDF à partir de plusieurs oldDF, j'utilise simplement une boucle for pour effectuer une itération sur pandas.DataFrame.append ()
128
geekidharsh

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.

97
Afshin Amiri

La bonne façon de créer un DataFrame

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).


Choses que vous ne devriez pas faire

append ou concat dans une boucle

Voici 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 boucle

J'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.

DataFrame vide de NaN

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 preuve est dans le pudding

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é.

enter image description here

Code de référence pour référence.

24
cs95