2012-06-14 36 views
10

Tôi muốn có thể tạo một Pandas DataFrame với MultiIndexes cho các hàng và chỉ mục cột và đọc nó từ một tệp văn bản ASCII. Dữ liệu của tôi trông giống như:Làm thế nào để viết/đọc một khung dữ liệu Pandas với MultiIndex từ/đến một tệp ASCII?

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 

Tôi đã thử df.to_csv()read_csv() nhưng họ không giữ chỉ số.

Tôi đã nghĩ đến việc có thể tạo một định dạng mới bằng cách sử dụng thêm dấu phân cách. Ví dụ: sử dụng hàng ---------------- để đánh dấu phần cuối của các chỉ mục cột và | để đánh dấu phần cuối của chỉ mục hàng. Vì vậy, nó sẽ trông như thế này:

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 

Pandas có cách viết/đọc DataFrames đến/từ tệp ASCII với MultiIndex không?

+0

Có, chỉ cần đặt multi_sparse thành False! :) –

Trả lời

11

Không chắc chắn phiên bản của gấu trúc bạn đang sử dụng nhưng với 0.7.3 bạn có thể xuất DataFrame của bạn vào một tập tin TSV và duy trì các chỉ số bằng cách làm này:

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

Lý do bạn cần phải xuất khẩu sang TSV so với CSV vì các tiêu đề cột có các ký tự , trong chúng. Điều này sẽ giải quyết phần đầu tiên của câu hỏi của bạn.

Phần thứ hai trở nên phức tạp hơn một chút kể từ khi tôi có thể nói, trước tiên bạn cần có ý tưởng về những gì bạn muốn DataFrame của mình chứa. Đặc biệt, bạn cần phải biết:

  1. Những cột trên TSV của bạn đại diện cho hàng MultiIndex
  2. và rằng phần còn lại của các cột cũng nên được chuyển đổi sang một MultiIndex

Để minh họa điều này, cho phép đọc lại các tập tin TSV chúng tôi lưu ở trên vào một mới DataFrame:

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

Vì vậy, chúng tôi cố gắng đọc mydf.tsv vào một số DataFrame có cùng chỉ mục hàng như df gốc. Nhưng:

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

Và lý do ở đây là vì gấu trúc (như xa như tôi có thể nói) không có cách nào phân tích các dòng tiêu đề một cách chính xác vào một MultiIndex.Như tôi đã đề cập ở trên, nếu bạn biết beorehand rằng phần đầu tập tin TSV của bạn đại diện cho một MultiIndex sau đó bạn có thể làm như sau để sửa lỗi này:

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

Tôi thích những gì bạn nghĩ ra. Tôi nghĩ rằng tôi vẫn sẽ tạo ra định dạng của riêng mình vì tôi không biết trước bao nhiêu cột được sử dụng cho chỉ mục. Cảm ơn. – dailyglen

4

Bạn có thể thay đổi các tùy chọn in bằng set_option:

display.multi_sparse :
: boolean
    Mặc định True, "sparsify" MultiIndex hiển thị
    (không hiển thị lặp lại yếu tố nồng độ bên ngoài trong các nhóm)

Bây giờ DataFrame sẽ được in như mong muốn:

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 

Lưu ý: trong phiên bản cũ gấu trúc này là pd.set_printoptions(multi_sparse=False).

Các vấn đề liên quan