2016-05-03 26 views
9

Aggiungo righe a un DataFrame panda all'interno di un ciclo for, ma alla fine il dataframe è sempre vuoto. Non voglio aggiungere le righe a un array e quindi chiamare il costruttore di DataFrame, perché il mio ciclo effettivo gestisce molti dati. Ho anche provato pd.concat senza successo. Qualcuno potrebbe evidenziare ciò che mi manca per far funzionare la dichiarazione append? Ecco un esempio fittizio:Uso di panda .append all'interno del ciclo

import pandas as pd 
import numpy as np 

data = pd.DataFrame([]) 

for i in np.arange(0, 4): 
    if i % 2 == 0: 
     data.append(pd.DataFrame({'A': i, 'B': i + 1}, index=[0]), ignore_index=True) 
    else: 
     data.append(pd.DataFrame({'A': i}, index=[0]), ignore_index=True) 

print data.head() 

Empty DataFrame 
Columns: [] 
Index: [] 
[Finished in 0.676s] 

risposta

6

È necessario impostare la variabile data uguale al frame di dati allegato. A differenza del metodo append su un elenco di pitone i panda append non avviene in luogo

import pandas as pd 
import numpy as np 

data = pd.DataFrame([]) 

for i in np.arange(0, 4): 
    if i % 2 == 0: 
     data = data.append(pd.DataFrame({'A': i, 'B': i + 1}, index=[0]), ignore_index=True) 
    else: 
     data = data.append(pd.DataFrame({'A': i}, index=[0]), ignore_index=True) 

print(data.head()) 

    A B 
0 0 1.0 
1 2 3.0 
2 3 NaN 
+0

Grazie che funziona! È piuttosto sciocco che non ci abbia pensato. – chizze

13

Ogni volta che si chiama aggiungere, Panda restituisce una copia del dataframe originale più la vostra nuova riga. Questa operazione è chiamata copia quadratica ed è un'operazione O (N^2) che diventerà rapidamente molto lenta (soprattutto perché hai molti dati).

Nel tuo caso, consiglierei di utilizzare elenchi, aggiungendoli a loro e chiamando il costruttore di dataframe.

a_list = [] 
b_list = [] 
for data in my_data: 
    a, b = process_data(data) 
    a_list.append(a) 
    b_list.append(b) 
df = pd.DataFrame({'A': a_list, 'B': b_list}) 
del a_list, b_list 

Tempi

%%timeit 
data = pd.DataFrame([]) 
for i in np.arange(0, 10000): 
    if i % 2 == 0: 
     data = data.append(pd.DataFrame({'A': i, 'B': i + 1}, index=[0]), ignore_index=True) 
else: 
    data = data.append(pd.DataFrame({'A': i}, index=[0]), ignore_index=True) 
1 loops, best of 3: 6.8 s per loop 

%%timeit 
a_list = [] 
b_list = [] 
for i in np.arange(0, 10000): 
    if i % 2 == 0: 
     a_list.append(i) 
     b_list.append(i + 1) 
    else: 
     a_list.append(i) 
     b_list.append(None) 
data = pd.DataFrame({'A': a_list, 'B': b_list}) 
100 loops, best of 3: 8.54 ms per loop 
+0

OK, quindi salvarlo su un array e quindi chiamare DataFrame è in realtà più veloce di allora. Grazie! – chizze

2

È possibile costruire la vostra dataframe senza un ciclo:

n = 4 
data = pd.DataFrame({'A': np.arange(n)}) 
data['B'] = np.NaN 
data.loc[data['A'] % 2 == 0, 'B'] = data['A'] + 1 

Per:

n = 10000 

Questo è un po 'più veloce:

%%timeit 
data = pd.DataFrame({'A': np.arange(n)}) 
data['B'] = np.NaN 
data.loc[data['A'] % 2 == 0, 'B'] = data['A'] + 1 

100 loops, best of 3: 3.3 ms per loop 

vs.

%%timeit 
a_list = [] 
b_list = [] 
for i in np.arange(n): 
    if i % 2 == 0: 
     a_list.append(i) 
     b_list.append(i + 1) 
    else: 
     a_list.append(i) 
     b_list.append(None) 
data1 = pd.DataFrame({'A': a_list, 'B': b_list}) 

100 loops, best of 3: 12.4 ms per loop