2012-06-14 6 views
10

Ich möchte in der Lage sein, eine Pandas DataFrame mit MultiIndexes für die Zeilen und den Spaltenindex zu erstellen und es aus einer ASCII-Textdatei zu lesen. Meine Daten wie folgt aussieht:Wie schreibe/lese ich einen Pandas DataFrame mit MultiIndex von/in eine ASCII-Datei?

col_indx = MultiIndex.from_tuples([('A', 'B', 'C'), ('A', 'B', 'C2'), ('A', 'B', 'C3'), 
            ('A', 'B2', 'C'), ('A', 'B2', 'C2'), ('A', 'B2', 'C3'), 
            ('A', 'B3', 'C'), ('A', 'B3', 'C2'), ('A', 'B3', 'C3'), 
            ('A2', 'B', 'C'), ('A2', 'B', 'C2'), ('A2', 'B', 'C3'), 
            ('A2', 'B2', 'C'), ('A2', 'B2', 'C2'), ('A2', 'B2', 'C3'), 
            ('A2', 'B3', 'C'), ('A2', 'B3', 'C2'), ('A2', 'B3', 'C3')], 
            names=['one','two','three']) 
row_indx = MultiIndex.from_tuples([(0, 'North', 'M'), 
            (1, 'East', 'F'), 
            (2, 'West', 'M'), 
            (3, 'South', 'M'), 
            (4, 'South', 'F'), 
            (5, 'West', 'F'), 
            (6, 'North', 'M'), 
            (7, 'North', 'M'), 
            (8, 'East', 'F'), 
            (9, 'South', 'M')], 
            names=['n', 'location', 'sex']) 
size=len(row_indx), len(col_indx) 
data = np.random.randint(0,10, size) 
df = DataFrame(data, index=row_indx, columns=col_indx) 
print df 

Ich habe versucht df.to_csv() und read_csv() aber sie halten den Index nicht.

Ich dachte an vielleicht ein neues Format mit zusätzlichen Delimetern erstellen. Verwenden Sie beispielsweise eine Zeile ----------------, um das Ende der Spaltenindizes zu markieren, und |, um das Ende eines Zeilenindex zu markieren. So würde es so aussehen:

one   | A A A A A A A A A A2 A2 A2 A2 A2 A2 A2 A2 A2 
two   | B B B B2 B2 B2 B3 B3 B3 B B B B2 B2 B2 B3 B3 B3 
three   | C C2 C3 C C2 C3 C C2 C3 C C2 C3 C C2 C3 C C2 C3 
-------------------------------------------------------------------------------------- 
n location sex :                  
0 North M | 2 3 9 1 0 6 5 9 5 9 4 4 0 9 6 2 6 1 
1 East  F | 6 2 9 2 7 0 0 3 7 4 8 1 3 2 1 7 7 5 
2 West  M | 5 8 9 7 6 0 3 0 2 5 0 3 9 6 7 3 4 9 
3 South M | 6 2 3 6 4 0 4 0 1 9 3 6 2 1 0 6 9 3 
4 South F | 9 6 0 0 6 1 7 0 8 1 7 6 2 0 8 1 5 3 
5 West  F | 7 9 7 8 2 0 4 3 8 9 0 3 4 9 2 5 1 7 
6 North M | 3 3 5 7 9 4 2 6 3 2 7 5 5 5 6 4 2 9 
7 North M | 7 4 8 6 8 4 5 7 9 0 2 9 1 9 7 9 5 6 
8 East  F | 1 6 5 3 6 4 6 9 6 9 2 4 2 9 8 4 2 4 
9 South M | 9 6 6 1 3 1 3 5 7 4 8 6 7 7 8 9 2 3 

Does Pandas hat einen Weg zu schreiben/lesen Datenrahmen zu/von ASCII-Dateien mit MultiIndexes?

+0

Ja, einfach multi_sparse auf False setzen! :) –

Antwort

11

nicht sicher, welche Version von Pandas Sie verwenden aber mit 0.7.3 können Sie Ihre DataFrame auf eine TSV-Datei und behalten die Indizes exportieren, indem Sie diese:

df.to_csv('mydf.tsv', sep='\t') 

Der Grund müssen Sie TSV gegen CSV exportieren ist da die Spaltenüberschriften , Zeichen in ihnen haben. Dies sollte den ersten Teil Ihrer Frage lösen.

Der zweite Teil wird ein bisschen komplizierter, da ich, soweit ich das beurteilen kann, vorher wissen müssen, was Ihr DataFrame enthalten soll. Insbesondere müssen Sie wissen:

  1. Welche Spalten auf Ihrem TSV die Zeile repräsentieren MultiIndex
  2. und dass der Rest der Spalten auch auf ein MultiIndex

konvertiert werden soll Um dies zu veranschaulichen, Hiermit kann der TSV-Datei zurückgelesen wir oben in eine neue DataFrame gespeichert:

In [1]: t_df = read_table('mydf.tsv', index_col=[0,1,2]) 
In [2]: all(t_df.index == df.index) 
Out[2]: True 

So konnten wirlesen 210 in eine DataFrame, die den gleichen Zeilenindex wie das Original df hat. Aber:

In [3]: all(t_df.columns == df.columns) 
Out[3]: False 

Und der Grund hier ist, weil Pandas (soweit ich das beurteilen kann) hat keine Möglichkeit, die Kopfzeile korrekt in eine MultiIndex Parsen.Wie ich bereits erwähnt, wenn Sie wissen, beorehand dass Ihre TSV Datei-Header ein MultiIndex stellt dann können Sie tun, die dieses Problem beheben folgende:

In [4]: from ast import literal_eval 
In [5]: t_df.columns = MultiIndex.from_tuples(t_df.columns.map(literal_eval).tolist(), 
               names=['one','two','three']) 
In [6]: all(t_df.columns == df.columns) 
Out[6]: True 
+0

Ich mag was du darausestelltest. Ich denke, ich werde immer noch mein eigenes Format erstellen, da ich im Voraus nicht weiß, wie viele Spalten für den Index verwendet werden. Vielen Dank. – dailyglen

4

Sie die Druckoptionen ändern set_option verwenden, können:

display.multi_sparse :
: boolean
    Standard True "sparsify" MultiIndex Anzeige
    (nicht Elemente in der äußeren Ebenen innerhalb von Gruppen wiederholt Display)

Nun wird der Datenrahmen wie gewünscht gedruckt werden:

In [11]: pd.set_option('multi_sparse', False) 

In [12]: df 
Out[12]: 
one    A A A A A A A A A A2 A2 A2 A2 A2 A2 A2 A2 A2 
two    B B B B2 B2 B2 B3 B3 B3 B B B B2 B2 B2 B3 B3 B3 
three   C C2 C3 C C2 C3 C C2 C3 C C2 C3 C C2 C3 C C2 C3 
n location sex                  
0 North M 2 1 6 4 6 4 7 1 1 0 4 3 9 2 0 0 6 4 
1 East  F 3 5 5 6 4 8 0 3 2 3 9 8 1 6 7 4 7 2 
2 West  M 7 9 3 5 0 1 2 8 1 6 0 7 9 9 3 2 2 4 
3 South M 1 0 0 3 5 7 7 0 9 3 0 3 3 6 8 3 6 1 
4 South F 8 0 0 7 3 8 0 8 0 5 5 6 0 0 0 1 8 7 
5 West  F 6 5 9 4 7 2 5 6 1 2 9 4 7 5 5 4 3 6 
6 North M 3 3 0 1 1 3 6 3 8 6 4 1 0 5 5 5 4 9 
7 North M 0 4 9 8 5 7 7 0 5 8 4 1 5 7 6 3 6 8 
8 East  F 5 6 2 7 0 6 2 7 1 2 0 5 6 1 4 8 0 3 
9 South M 1 2 0 6 9 7 5 3 3 8 7 6 0 5 4 3 5 9 

Hinweis: in älteren Versionen Pandas war pd.set_printoptions(multi_sparse=False).

Verwandte Themen