2016-05-03 13 views
9

Ich bin Zeilen an eine Pandas DataFrame innerhalb einer for-Schleife anhängen, aber am Ende ist das Datenfeld immer leer. Ich möchte die Zeilen nicht zu einem Array hinzufügen und dann den DataFrame-Konstruktor aufrufen, da meine eigentliche for-Schleife viele Daten verarbeitet. Ich versuchte auch pd.concat ohne Erfolg. Könnte jemand hervorheben, was ich vermisse, damit die Append-Anweisung funktioniert? Hier ist ein Dummy-Beispiel:Verwenden von Pandas. Anhang innerhalb von Schleife

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] 

Antwort

6

Sie benötigen die die Variable data gleich der angehängten Datenrahmen zu setzen. Im Gegensatz zu der append Methode auf einer Python-Liste die Pandas append geschieht nicht an Ort und Stelle

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

Dank, das funktioniert! Ein bisschen albern, dass ich nicht daran gedacht habe. – chizze

13

Jedes Mal, wenn Sie anhängen aufrufen, gibt Pandas eine Kopie des ursprünglichen Datenrahmen plus Ihre neue Zeile. Dies wird quadratische Kopie genannt, und es ist eine O (N^2) -Operation, die sehr schnell sehr langsam wird (besonders, da Sie viele Daten haben).

In Ihrem Fall würde ich empfehlen, Listen zu verwenden, an sie anzufügen und dann den Dataframe-Konstruktor aufzurufen.

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 

Timings

%%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

In Ordnung, so dass es in einem Array gespeichert wird und dann den DataFrame aufruft, ist dann tatsächlich schneller. Vielen Dank! – chizze

2

Sie Ihre Datenrahmen ohne eine Schleife bauen:

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

Für:

n = 10000 

Dieses etwas schneller ist:

%%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 

gegen

%%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 
Verwandte Themen