Creare un DataFrame Pandas vuoto e poi riempirlo?

Parto dalla documentazione di pandas DataFrame qui: http://pandas.pydata.org/pandas-docs/stable/dsintro.html

Vorrei riempire iterativamente il DataFrame con valori in un calcolo di tipo serie temporale. Quindi, fondamentalmente, vorrei inizializzare il DataFrame con le colonne A, B e le righe di timestamp, tutte 0 o tutte NaN.

Aggiungerei poi dei valori iniziali e passerei su questi dati calcolando la nuova riga dalla riga precedente, diciamo row[A][t] = row[A][t-1]+1 o così.

Attualmente sto usando il codice qui sotto, ma sento che è un po' brutto e ci deve essere un modo per farlo direttamente con un DataFrame, o semplicemente un modo migliore in generale. Nota: sto usando Python 2.7.

import datetime as dt
import pandas as pd
import scipy as s

if __name__ == '__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
Soluzione

Ecco un paio di suggerimenti:

Usate date_range per l'indice:

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']

Nota: potremmo creare un DataFrame vuoto (con NaNs) semplicemente scrivendo:

df_ = pd.DataFrame(index=index, columns=columns)
df_ = df_.fillna(0) # with 0s rather than NaNs

Per fare questo tipo di calcoli per i dati, usate un array numpy:

data = np.array([np.arange(10)]*3).T

Quindi possiamo creare il 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
Commentari (7)

Se volete semplicemente creare un frame di dati vuoto e riempirlo successivamente con alcuni frame di dati in arrivo, provate questo:

In questo esempio sto usando questo documento pandas per creare un nuovo frame di dati e poi uso append per scrivere nel newDF con i dati del oldDF.


Dai un'occhiata a questo

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 
  • se devo continuare ad aggiungere nuovi dati in questa newDF da più di una vecchiaDF, uso semplicemente un ciclo for per iterare su pandas.DataFrame.append()
Commentari (3)

Se volete avere i vostri nomi di colonna al loro posto fin dall'inizio, usate questo approccio:

import pandas as pd

col_names =  ['A', 'B', 'C']
my_df  = pd.DataFrame(columns = col_names)
my_df

Se vuoi aggiungere un record al dataframe sarebbe meglio usare:

my_df.loc[len(my_df)] = [2, 4, 5]

Potresti anche voler passare un dizionario:

my_dic = {'A':2, 'B':4, 'C':5}
my_df.loc[len(my_df)] = my_dic 

Tuttavia, se vuoi aggiungere un altro dataframe a my_df fai come segue:

col_names =  ['A', 'B', 'C']
my_df2  = pd.DataFrame(columns = col_names)
my_df = my_df.append(my_df2)

Se state aggiungendo righe all'interno di un ciclo considerate i problemi di performance:
Per circa i primi 1000 record "my_df.loc" le prestazioni sono migliori, ma diventano gradualmente più lente aumentando il numero di record nel ciclo.

Se avete intenzione di fare diete all'interno di un grande ciclo (diciamo 10M di record o giù di lì):
È meglio usare un misto di questi due; riempire un dataframe con iloc fino a quando la dimensione non diventa circa 1000, poi aggiungerlo al dataframe originale e svuotare il dataframe temporaneo. Questo aumenterebbe le tue prestazioni di circa 10 volte.

Commentari (0)