2014-06-18 41 views
9

Tôi có một dataframe, grouped, với các cột multiindex như sau:Pandas dataframe với cột multiindex - merge mức

import pandas as pd 
codes = ["one","two","three"]; 
colours = ["black", "white"]; 
textures = ["soft", "hard"]; 
N= 100 # length of the dataframe 
df = pd.DataFrame({ 'id' : range(1,N+1), 
        'weeks_elapsed' : [random.choice(range(1,25)) for i in range(1,N+1)], 
        'code' : [random.choice(codes) for i in range(1,N+1)], 
        'colour': [random.choice(colours) for i in range(1,N+1)], 
        'texture': [random.choice(textures) for i in range(1,N+1)], 
        'size': [random.randint(1,100) for i in range(1,N+1)], 
        'scaled_size': [random.randint(100,1000) for i in range(1,N+1)] 
        }, columns= ['id', 'weeks_elapsed', 'code','colour', 'texture', 'size', 'scaled_size']) 
grouped = df.groupby(['code', 'colour']).agg({'size': [np.sum, np.average, np.size, pd.Series.idxmax],'scaled_size': [np.sum, np.average, np.size, pd.Series.idxmax]}).reset_index() 

>> grouped 
    code colour  size       scaled_size       
        sum average size idxmax   sum average size idxmax 
0 one black 1031 60.647059 17  81  185.153944 10.891408 17  47 
1 one white  481 37.000000 13  53  204.139249 15.703019 13  53 
2 three black  822 48.352941 17  6  123.269405 7.251141 17  31 
3 three white 1614 57.642857 28  50  285.638337 10.201369 28  37 
4 two black  523 58.111111  9  85  80.908912 8.989879  9  88 
5 two white  669 41.812500 16  78  82.098870 5.131179 16  78 
[6 rows x 10 columns] 

Làm thế nào tôi có thể làm phẳng/sáp nhập các mức chỉ số cột như: "Level1 | level2", ví dụ size|sum, scaled_size|sum. v.v. Nếu điều này là không thể, có cách nào để groupby() như tôi đã làm ở trên mà không tạo cột đa chỉ mục không?

Trả lời

6

bạn có thể luôn luôn thay đổi các cột:

grouped.columns = ['%s%s' % (a, '|%s' % b if b else '') for a, b in grouped.columns] 
+1

nếu một trong các cột ở cấp 1 bằng' 0', thì biểu thức ở trên sẽ bỏ qua nó ở đây: 'b if b else '' '. Thay vào đó, tôi đã sử dụng 'b! = ''', Vì vậy 'grouped.columns = ['% s% s'% (a, '|% s'% b nếu b! = '' Else '') cho a, b trong grouped.columns] '. Điều này có thể hữu ích sau khi sử dụng 'groupby' liệt kê các cột có số bắt đầu từ 0. –

+1

sẽ có vấn đề với' None 'trong đó, vì vậy bạn phải làm' if (b == 0 hoặc b) ' , nhưng vẫn là một cuộc gọi tốt – acushner

+0

@acusher, bạn phải, mặc dù 'nếu b không phải là None' nên cách đơn giản để thể hiện ... –

0

tôi không chắc chắn nếu tôi hiểu những gì bạn có ý nghĩa;) nhưng bạn có thể kết hợp hai cột với dữ liệu chuỗi thành chỉ số như thế:

df['merged_ix'] = df.code + '|' + df.colour 
df.set_index(df.merged_ix, inplace=True) 
+0

Cảm ơn bạn, nhưng nó không phải là những gì tôi đang yêu cầu . Tôi đã chỉnh sửa câu hỏi để làm cho nó rõ ràng hơn. Tôi muốn loại bỏ hai cấp độ trong các tên cột. Nếu có hai cấp độ, ni muốn kết hợp chúng thành một, như 'size | sum' – Rhubarb

9

Có tiềm năng một cách tốt hơn, nhiều cách hơn để làm phẳng các cột multiindex.

grouped.columns = grouped.columns.map('|'.join) 

print(grouped) 

Output:

code| colour| size|sum size|average size|size size|idxmax \ 
0 one black  862  53.875000   16   14 
1 one white  554  46.166667   12   18 
2 three black  842  49.529412   17   90 
3 three white  740  56.923077   13   97 
4 two black  1541  61.640000   25   50 

    scaled_size|sum scaled_size|average scaled_size|size scaled_size|idxmax 
0    6980   436.250000    16     77 
1    6101   508.416667    12     13 
2    7889   464.058824    17     64 
3    6329   486.846154    13     73 
4   12809   512.360000    25     23 

Sửa bàn cột số sử dụng:

grouped.columns = grouped.columns.map('{0[0]}|{0[1]}'.format) 

Output:

code| colour| size|sum size|average size|size size|idxmax \ 
0 one black  734  52.428571   14   30 
1 one white  1110  65.294118   17   88 
2 three black  930  51.666667   18   3 
3 three white  1140  51.818182   22   20 
4 two black  656  38.588235   17   77 
5 two white  704  58.666667   12   17 

    scaled_size|sum scaled_size|average scaled_size|size scaled_size|idxmax 
0    8229   587.785714    14     57 
1    8781   516.529412    17     73 
2   10743   596.833333    18     21 
3   10240   465.454545    22     26 
4    9982   587.176471    17     16 
5    6537   544.750000    12     49 
+0

nó không hoạt động khi bạn có các cột số ' MultiIndex (levels = [ [u'col_a ', u'col_b', u'col_c '], [7950230.0, 12304568.0]], nhãn = [[0, 0, 1], [0, 1, 1]], tên = [lev , sublev ']) ' nó trả về ' LoạiError: mục chuỗi 1: chuỗi được mong đợi, tìm thấy float' –

+0

@PabloA grouped.columns.map ('{0 [0]} | {0 [1]}' định dạng) –

+1

Giải pháp tuyệt vời. Pythonic và linh hoạt. – Kevin

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