2016-12-19 6 views
5

Untertitel: Dumb it down Pandas, hör auf, clever zu sein.Concat Liste der Pandas Datenrahmen, aber ignorieren Spalte Name

Ich habe eine Liste (res) von Single-Column Pandas Datenrahmen, jeder enthält die gleiche Art von numerischen Daten, aber jeder mit einem anderen Spaltennamen. Die Zeilenindizes haben keine Bedeutung. Ich möchte sie in einen einzigen, sehr langen, einspaltigen Datenrahmen einfügen.

Wenn ich pd.concat(res) mache ich bekomme eine Spalte pro Eingabedatei (und lädt und lädt von NaN-Zellen). Ich habe verschiedene Werte für die Parameter (*) ausprobiert, aber keine, die das tun, wonach ich suche.

Edit: Beispieldaten:

res = [ 
    pd.DataFrame({'A':[1,2,3]}), 
    pd.DataFrame({'B':[9,8,7,6,5,4]}), 
    pd.DataFrame({'C':[100,200,300,400]}), 
] 

Ich habe eine hässliche-Hack-Lösung: jeden Datenrahmen kopieren und einen neuen Spaltennamen geben:

newList = [] 
for r in res: 
    r.columns = ["same"] 
    newList.append(r) 
pd.concat(newList, ignore_index=True) 

Sicher, dass nicht der beste Weg ist, es zu tun??

BTW, ist ähnlich, aber meine Frage ist noch einfacher, da ich nicht möchte, dass der Index beibehalten wird. (Ich beginne auch mit einer Liste von N einspaltigen Datenrahmen, nicht einem einzelnen N-Spalten-Datenrahmen.)

*: z.B. axis=0 ist das Standardverhalten. axis=1 gibt einen Fehler aus. join="inner" ist nur dumm (ich bekomme nur den Index). ignore_index=True nummeriert den Index, aber ich bekomme immer noch viele Spalten, viele NaNs.


UPDATE für leere Listen

Ich hatte Probleme mit (mit allen gegebenen Lösungen), wenn die Daten eine leere Liste haben, so etwas wie:

res = [ 
    pd.DataFrame({'A':[1,2,3]}), 
    pd.DataFrame({'B':[9,8,7,6,5,4]}), 
    pd.DataFrame({'C':[]}), 
    pd.DataFrame({'D':[100,200,300,400]}), 
] 

Der Trick bestand darin, erzwinge den Typ, indem du .astype('float64') hinzufügst. Z.B.

pd.Series(np.concatenate([df.values.ravel().astype('float64') for df in res])) 

oder:

pd.concat(res,axis=0).astype('float64').stack().reset_index(drop=True) 

Antwort

2

würde ich Liste comphrension solche Verwendung hat:

import pandas as pd 
res = [ 
    pd.DataFrame({'A':[1,2,3]}), 
    pd.DataFrame({'B':[9,8,7,6,5,4]}), 
    pd.DataFrame({'C':[100,200,300,400]}), 
] 


x = [] 
[x.extend(df.values.tolist()) for df in res] 
pd.DataFrame(x) 

Out[49]: 
     0 
0  1 
1  2 
2  3 
3  9 
4  8 
5  7 
6  6 
7  5 
8  4 
9 100 
10 200 
11 300 
12 400 

I Geschwindigkeit für Sie getestet.

%timeit x = []; [x.extend(df.values.tolist()) for df in res]; pd.DataFrame(x) 
10000 loops, best of 3: 196 µs per loop 
%timeit pd.Series(pd.concat(res, axis=1).values.ravel()).dropna() 
1000 loops, best of 3: 920 µs per loop 
%timeit pd.concat(res, axis=1).stack().reset_index(drop=True) 
1000 loops, best of 3: 902 µs per loop 
%timeit pd.DataFrame(pd.concat(res, axis=1).values.ravel(), columns=['col']).dropna() 
1000 loops, best of 3: 1.07 ms per loop 
%timeit pd.Series(np.concatenate([df.values.ravel() for df in res])) 
10000 loops, best of 3: 70.2 µs per loop 

sieht aus wie

pd.Series(np.concatenate([df.values.ravel() for df in res])) 

die schnellste ist.

+0

Könnte sein 'pd.concat ([x.rename (Spalten = lambda c: 'same') für x in res], ignore_index = True)' – jrovegno

+0

Danke für die Timings; es war in diesem Fall nicht zeitempfindlich, aber es ist gut, das schnellste Idiom zu kennen, falls ich es jemals für eine große Datenmenge brauche. –

5

Ich glaube, Sie brauchen concat mit stack:

print (pd.concat(res, axis=1)) 
    A B  C 
0 1.0 9 100.0 
1 2.0 8 200.0 
2 3.0 7 300.0 
3 NaN 6 400.0 
4 NaN 5 NaN 
5 NaN 4 NaN 

print (pd.concat(res, axis=1).stack().reset_index(drop=True)) 
0  1.0 
1  9.0 
2  100.0 
3  2.0 
4  8.0 
5  200.0 
6  3.0 
7  7.0 
8  300.0 
9  6.0 
10 400.0 
11  5.0 
12  4.0 
dtype: float64 

Eine andere Lösung mit numpy.ravel für Abflachung:

print (pd.Series(pd.concat(res, axis=1).values.ravel()).dropna()) 
0  1.0 
1  9.0 
2  100.0 
3  2.0 
4  8.0 
5  200.0 
6  3.0 
7  7.0 
8  300.0 
10  6.0 
11 400.0 
13  5.0 
16  4.0 
dtype: float64 

print (pd.DataFrame(pd.concat(res, axis=1).values.ravel(), columns=['col']).dropna()) 
     col 
0  1.0 
1  9.0 
2 100.0 
3  2.0 
4  8.0 
5 200.0 
6  3.0 
7  7.0 
8 300.0 
10 6.0 
11 400.0 
13 5.0 
16 4.0 

Lösung mit list comprehension:

print (pd.Series(np.concatenate([df.values.ravel() for df in res]))) 
0  1 
1  2 
2  3 
3  9 
4  8 
5  7 
6  6 
7  5 
8  4 
9  100 
10 200 
11 300 
12 400 
dtype: int64 
+0

Entlang dieser Zeilen, aber ich habe eine Liste von 1-Spalte Datenrahmen, nicht die 6-Spalten-Datenrahmen in Ihrem Beispiel. –

+0

@DarrenCook dann 'df.values' würde nicht funktionieren? – MMF

+0

Ich habe der Frage gerade Beispieldaten hinzugefügt. –

Verwandte Themen