2016-08-16 27 views
9

Nếu tôi có một dataframe đơn giản:Pandas thiết lập đa-index trên các hàng, sau đó transposing tới cột

print(a) 

    one two three 
0 A 1  a 
1 A 2  b 
2 B 1  c 
3 B 2  d 
4 C 1  e 
5 C 2  f 

tôi có thể dễ dàng tạo ra một đa-index trên các hàng bằng cách phát hành:

a.set_index(['one', 'two']) 

     three 
one two  
A 1  a 
    2  b 
B 1  c 
    2  d 
C 1  e 
    2  f 

Có cách nào tương tự dễ dàng để tạo nhiều chỉ mục trên các cột không?

Tôi muốn kết thúc với:

one A  B  C 
    two 1 2 1 2 1 2 
    0 a b c d e f 

Trong trường hợp này, nó sẽ là khá đơn giản để tạo ra các hàng đa-index và sau đó transpose nó, nhưng trong ví dụ khác, tôi sẽ muốn tạo nhiều chỉ mục trên cả hàng và cột.

+0

Dường như a.pivot (index = 'one', cột = 'hai', giá trị = 'ba') là nhận được gần hơn với những gì tôi muốn (trích xuất thông tin từ df và biến chúng thành cột), mặc dù tôi đã không hoàn toàn tìm ra cách để làm cho đa chỉ số. – sheridp

+0

Tôi không nghĩ rằng bạn muốn "đặt nhiều chỉ mục trên cột", tôi nghĩ bạn muốn đặt nó trên hàng, sau đó chuyển hàng sang cột? Vui lòng chỉnh sửa câu hỏi của bạn để rõ ràng hơn – smci

Trả lời

4

Có! Nó được gọi là chuyển vị.

a.set_index(['one', 'two']).T 

enter image description here


Hãy mượn từ bài @ ragesz vì họ đã sử dụng một ví dụ tốt hơn nhiều để chứng minh với.

df = pd.DataFrame({'a':['foo_0', 'bar_0', 1, 2, 3], 'b':['foo_0', 'bar_1', 11, 12, 13], 
    'c':['foo_1', 'bar_0', 21, 22, 23], 'd':['foo_1', 'bar_1', 31, 32, 33]}) 

df.T.set_index([0, 1]).T 

enter image description here

+2

OP, không muốn sử dụng chuyển đổi vì họ muốn có nhiều chỉ mục trên các cột và hàng. – Merlin

+0

Có thể một '.reset_index (drop = True)' tại và sẽ là cần thiết, và trong một dòng mới là 'df.columns.name = ['first', 'second']' để đổi tên các tiêu đề cột. – ragesz

+0

@Merlin OK. Bạn có thể chuyển đổi sau đó set_index, transpose rồi set_index. Nếu OP đưa ra một ví dụ mà họ muốn cho cả hai, tôi vui mừng cho thấy nó được thực hiện như thế nào. Tôi sẽ làm ngay bây giờ, nhưng tôi phải chạy một lúc. – piRSquared

0

Tôi nghĩ câu trả lời ngắn gọn là NO. Để có cột nhiều chỉ mục, khung dữ liệu phải có hai (hoặc nhiều) hàng được chuyển đổi thành tiêu đề (như cột cho hàng nhiều hàng). Nếu bạn có loại khung dữ liệu này, việc tạo tiêu đề nhiều chỉ mục không quá khó. Nó có thể được thực hiện trong một dòng rất dài mã, và bạn có thể tái sử dụng nó ở bất kỳ dataframe khác, chỉ số dòng của tiêu đề nên được giữ trong tâm trí & thay đổi nếu khác:

df = pd.DataFrame({'a':['foo_0', 'bar_0', 1, 2, 3], 'b':['foo_0', 'bar_1', 11, 12, 13], 
    'c':['foo_1', 'bar_0', 21, 22, 23], 'd':['foo_1', 'bar_1', 31, 32, 33]}) 

Các dataframe:

 a  b  c  d 
0 foo_0 foo_0 foo_1 foo_1 
1 bar_0 bar_1 bar_0 bar_1 
2  1  11  21  31 
3  2  12  22  32 
4  3  13  23  33 

Tạo đối tượng đa-index:

arrays = [df.iloc[0].tolist(), df.iloc[1].tolist()] 
tuples = list(zip(*arrays)) 
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second']) 

df.columns = index 

multi-index kết quả tiêu đề:

first foo_0   foo_1  
second bar_0 bar_1 bar_0 bar_1 
0  foo_0 foo_0 foo_1 foo_1 
1  bar_0 bar_1 bar_0 bar_1 
2   1  11  21  31 
3   2  12  22  32 
4   3  13  23  33 

Cuối cùng chúng ta cần phải thả 0-1 hàng sau đó đặt lại chỉ mục hàng:

df = df.iloc[2:].reset_index(drop=True) 

Phiên bản "một dòng" (chỉ có điều bạn phải thay đổi là để xác định chỉ số tiêu đề và dataframe bản thân):

idx_first_header = 0 
idx_second_header = 1 

df.columns = pd.MultiIndex.from_tuples(list(zip(*[df.iloc[idx_first_header].tolist(), 
    df.iloc[idx_second_header].tolist()])), names=['first', 'second']) 

df = df.drop([idx_first_header, idx_second_header], axis=0).reset_index(drop=True) 
1

Bạn có thể sử dụng pivot_table tiếp theo là một loạt các thao tác trên dataframe để có được những hình thức mong muốn:

df_pivot = pd.pivot_table(df, index=['one', 'two'], values='three', aggfunc=np.sum) 

def rename_duplicates(old_list): # Replace duplicates in the index with an empty string 
    seen = {} 
    for x in old_list: 
     if x in seen: 
      seen[x] += 1 
      yield " " 
     else: 
      seen[x] = 0 
      yield x 

col_group = df_pivot.unstack().stack().reset_index(level=-1) 
col_group.index = rename_duplicates(col_group.index.tolist()) 
col_group.index.name = df_pivot.index.names[0] 
col_group.T 

one A  B  C 
two 1 2 1 2 1 2 
0 a b c d e f 
Các vấn đề liên quan