2015-07-09 39 views
7

Tôi có một dataframe gấu trúc với hai biến id:Unmelt Pandas DataFrame

df = pd.DataFrame({'id': [1,1,1,2,2,3], 
       'num': [10,10,12,13,14,15], 
       'q': ['a', 'b', 'd', 'a', 'b', 'z'], 
       'v': [2,4,6,8,10,12]}) 

    id num q v 
0 1 10 a 2 
1 1 10 b 4 
2 1 12 d 6 
3 2 13 a 8 
4 2 14 b 10 
5 3 15 z 12 

tôi có thể xoay bảng với:

df.pivot('id','q','v') 

Và kết thúc với một cái gì đó gần gũi:

q a b d z 
id     
1 2 4 6 NaN 
2 8 10 NaN NaN 
3 NaN NaN NaN 12 

Tuy nhiên, những gì tôi thực sự muốn là (hình thức ban đầu chưa được tiết lộ):

id num a b d z    
1 10 2 4 NaN NaN 
1 12 NaN NaN 6 NaN 
2 13 8 NaN NaN NaN 
2 14 NaN 10 NaN NaN 
3 15 NaN NaN NaN 12 

Nói cách khác:

  1. 'id' và 'num' chỉ số của tôi (bình thường, tôi đã chỉ nhìn thấy một trong hai 'id' hoặc 'num' là chỉ số nhưng tôi cần cả hai kể từ khi tôi m cố gắng để lấy lại hình thức lớn nằm gốc)
  2. 'q' là cột của tôi
  3. 'v' là những giá trị của mình trong bảng

cập nhật

Tôi tìm thấy một giải pháp gần từ Wes McKinney's blog:

df.pivot_table(index=['id','num'], columns='q') 

     v    
q  a b d z 
id num     
1 10 2 4 NaN NaN 
    12 NaN NaN 6 NaN 
2 13 8 NaN NaN NaN 
    14 NaN 10 NaN NaN 
3 15 NaN NaN NaN 12 

Tuy nhiên, định dạng là không hoàn toàn giống như những gì tôi muốn ở trên.

Trả lời

9

Bạn đang slaw thực sự chặt chẽ. Chỉ cần đổi tên chỉ mục cột của bạn thành Không và bạn đã có những gì bạn muốn.

df2 = df.pivot_table(index=['id','num'], columns='q') 
df2.columns = df2.columns.droplevel().rename(None) 
df2.reset_index().fillna("null").to_csv("test.csv", sep="\t", index=None) 

Note rằng cột 'v' dự kiến ​​sẽ có dạng số theo mặc định để nó có thể được tổng hợp. Nếu không, Pandas sẽ báo lỗi ra với:

DataError: No numeric types to aggregate 

To resolve this, bạn có thể xác định chức năng tập hợp của riêng bạn bằng cách sử dụng một chức năng tùy chỉnh lambda:

df2 = df.pivot_table(index=['id','num'], columns='q', aggfunc= lambda x: x) 
+0

Ahhh, tôi đã rất gần! Tôi biết rằng nó đã làm với 'df.columns.name' nhưng không thể tìm ra cách sử dụng' đổi tên' một cách thích hợp. Cảm ơn bạn đã giúp đỡ! – slaw

+1

Lưu ý quan trọng: "chặt chẽ" âm thanh như "xà lách". –

0

đã đưa ra một giải pháp gần

df2 = df.pivot_table(index=['id','num'], columns='q') 
df2.columns = df2.columns.droplevel() 
df2.reset_index().fillna("null").to_csv("test.csv", sep="\t", index=None) 

Vẫn không thể tìm ra cách để thả 'q' từ dataframe

5

Bạn có thể sử dụng set_indexunstack

In [18]: df.set_index(['id', 'num', 'q'])['v'].unstack().reset_index() 
Out[18]: 
q id num a  b d  z 
0 1 10 2.0 4.0 NaN NaN 
1 1 12 NaN NaN 6.0 NaN 
2 2 13 8.0 NaN NaN NaN 
3 2 14 NaN 10.0 NaN NaN 
4 3 15 NaN NaN NaN 12.0 
+0

Điều này sạch hơn nhiều so với câu trả lời được chấp nhận. Cảm ơn! – kev8484

+0

Cảm ơn bạn. pandas.pivot() với nhiều cột chỉ mục không đơn giản như tôi hy vọng và giải pháp này hoạt động thay thế. –

1

bạn có thể xóa tên q.

df1.columns=df1.columns.tolist() 

câu trả lời của Zero + q = loại bỏ

df1 = df.set_index(['id', 'num', 'q'])['v'].unstack().reset_index() 
df1.columns=df1.columns.tolist() 

    id num a  b d  z 
0 1 10 2.0 4.0 NaN NaN 
1 1 12 NaN NaN 6.0 NaN 
2 2 13 8.0 NaN NaN NaN 
3 2 14 NaN 10.0 NaN NaN 
4 3 15 NaN NaN NaN 12.0