2013-09-04 53 views
5

Sử dụng gấu trúc, có thể tính toán một bảng chéo đơn (hoặc bảng tổng hợp) có chứa các giá trị được tính từ hai hàm khác nhau không?cách sử dụng hai hàm khác nhau trong crosstab/pivot_table trong gấu trúc?

import pandas as pd 
import numpy as np 

c1 = np.repeat(['a','b'], [50, 50], axis=0) 
c2 = list('xy'*50) 
c3 = np.repeat(['G1','G2'], [50, 50], axis=0) 
np.random.shuffle(c3) 
c4=np.repeat([1,2], [50,50],axis=0) 
np.random.shuffle(c4) 
val = np.random.rand(100) 

df = pd.DataFrame({'c1':c1, 'c2':c2, 'c3':c3, 'c4':c4, 'val':val}) 

frequencyTable = pd.crosstab([df.c1,df.c2],[df.c3,df.c4]) 
meanVal = pd.crosstab([df.c1,df.c2],[df.c3,df.c4],values=df.val,aggfunc=np.mean) 

Vì vậy, cả các hàng và các cột đều giống nhau ở cả hai bảng, nhưng những gì tôi thực sự muốn là một bảng với cả hai tần số và giá trị trung bình:

c3   G1      G2   
c4  1    2    1    2 
c1 c2 freq val  freq val  freq val  freq val   
a x 6 0.624931 5 0.582268 8 0.528231 6 0.362804 
    y 7 0.493890 8 0.465741 3 0.613126 7 0.312894 
b x 9 0.488255 5 0.804015 6 0.722640 5 0.369480 
    y 6 0.462653 4 0.506791 5 0.583695 10 0.517954 
+0

Bạn đã thử sử dụng 'aggfunc = [func1, func2]'? Tôi không có ý tưởng nếu điều này hoạt động nhưng tôi nghĩ rằng tôi đã nhìn thấy nó trước khi một nơi nào đó. – Brian

+0

@ Brian: Vâng, tôi vừa thử câu trả lời của joris, và nó hoạt động rất tốt! Cảm ơn nhiều! – HappyPy

+1

Tôi chỉ nên bắt đầu đăng ý kiến ​​của tôi như là câu trả lời :-p – Brian

Trả lời

10

Bạn có thể đưa ra một danh sách các chức năng:

pd.crosstab([df.c1,df.c2], [df.c3,df.c4], values=df.val, aggfunc=[len, np.mean]) 

Nếu bạn muốn bàn như trong câu hỏi của bạn, bạn sẽ phải sắp xếp lại các mức một chút:

In [42]: table = pd.crosstab([df.c1,df.c2], [df.c3,df.c4], values=df.val, aggfunc=[len, np.mean]) 

In [43]: table 
Out[43]: 
     len    mean        
c3  G1  G2   G1     G2   
c4  1 2 1 2   1   2   1   2 
c1 c2              
a x  4 6 8 7 0.303036 0.414474 0.624900 0.425234 
    y  5 5 8 7 0.543363 0.480419 0.583499 0.637657 
b x 10 6 4 5 0.400279 0.436929 0.442924 0.287572 
    y  6 8 5 6 0.400427 0.623319 0.764506 0.408708 

In [44]: table.reorder_levels([1, 2, 0], axis=1).sort_index(axis=1) 
Out[44]: 
c3  G1       G2       
c4  1    2    1    2   
     len  mean len  mean len  mean len  mean 
c1 c2                
a x  4 0.303036 6 0.414474 8 0.624900 7 0.425234 
    y  5 0.543363 5 0.480419 8 0.583499 7 0.637657 
b x 10 0.400279 6 0.436929 4 0.442924 5 0.287572 
    y  6 0.400427 8 0.623319 5 0.764506 6 0.408708 
+0

Chà, thật đơn giản :) Rất cám ơn! – HappyPy

+0

BTW, có thể tạo các cột "len" và "có nghĩa là" của riêng chúng khi định hình lại với sự tan chảy không? Tôi đã thử: pd.melt (table.reset_index(), id_vars = ['c1', 'c2']), nhưng tôi nhận được một cột có tên "NaN" với "len" và "mean" là các phần tử. Cảm ơn! – HappyPy

+1

Bạn chính xác có ý nghĩa gì với "cột của riêng họ"? Bạn có muốn một cột có "trung bình" và một cột có "len" bao quanh các cột "c1", "c2", "c3", "c4", như bạn sẽ nhận được với 'df.groupby ([" c1 ", "c2", "c3", "c4"]) tổng hợp ([len, np.mean]). reset_index() '? Trong trường hợp đó bạn có thể làm điều đó trực tiếp thay vì qua crosstab và tan chảy. – joris