2016-02-15 24 views
16

Tôi muốn chạy một trục xoay trên gấu trúc DataFrame, với chỉ mục là hai cột, không phải một cột. Ví dụ: một trường cho năm, một trường cho tháng, trường 'item' hiển thị mục 'item 1' và 'item 2' và trường 'value' có giá trị bằng số. Tôi muốn chỉ số là năm + tháng.gấu trúc: làm thế nào để chạy một trục với nhiều chỉ mục?

Cách duy nhất tôi quản lý để làm việc này là kết hợp hai trường thành một, sau đó tách chúng lại. Có cách nào tốt hơn?

Mã tối thiểu được sao chép bên dưới. Cảm ơn rất nhiều!

PS Có, tôi biết có các câu hỏi khác với từ khóa 'pivot' và 'multi-index', nhưng tôi không hiểu liệu/làm thế nào chúng có thể giúp tôi với câu hỏi này.

import pandas as pd 
import numpy as np 

df= pd.DataFrame() 
month = np.arange(1, 13) 
values1 = np.random.randint(0, 100, 12) 
values2 = np.random.randint(200, 300, 12) 


df['month'] = np.hstack((month, month)) 
df['year'] = 2004 
df['value'] = np.hstack((values1, values2)) 
df['item'] = np.hstack((np.repeat('item 1', 12), np.repeat('item 2', 12))) 

# This doesn't work: 
# ValueError: Wrong number of items passed 24, placement implies 2 
# mypiv = df.pivot(['year', 'month'], 'item', 'value') 

# This doesn't work, either: 
# df.set_index(['year', 'month'], inplace=True) 
# ValueError: cannot label index with a null key 
# mypiv = df.pivot(columns='item', values='value') 

# This below works but is not ideal: 
# I have to first concatenate then separate the fields I need 
df['new field'] = df['year'] * 100 + df['month'] 

mypiv = df.pivot('new field', 'item', 'value').reset_index() 
mypiv['year'] = mypiv['new field'].apply(lambda x: int(x)/100) 
mypiv['month'] = mypiv['new field'] % 100 
+3

Tôi đã cung cấp một số ví dụ chi tiết và cách tiếp cận thay thế trong [** Hỏi & Đáp **] này (https://stackoverflow.com/q/47152691/2336654) – piRSquared

Trả lời

21

Bạn có thể nhóm và sau đó hủy liên kết.

>>> df.groupby(['year', 'month', 'item'])['value'].sum().unstack('item') 
item  item 1 item 2 
year month     
2004 1   33  250 
    2   44  224 
    3   41  268 
    4   29  232 
    5   57  252 
    6   61  255 
    7   28  254 
    8   15  229 
    9   29  258 
    10   49  207 
    11   36  254 
    12   23  209 

Hoặc sử dụng pivot_table:

>>> df.pivot_table(values='value', index=['year', 'month'], columns='item') 
item  item 1 item 2 
year month     
2004 1   33  250 
    2   44  224 
    3   41  268 
    4   29  232 
    5   57  252 
    6   61  255 
    7   28  254 
    8   15  229 
    9   29  258 
    10   49  207 
    11   36  254 
    12   23  209 
10

Tôi tin rằng nếu bạn bao gồm item trong MultiIndex của bạn, sau đó bạn chỉ có thể unstack:

df.set_index(['year', 'month', 'item']).unstack(level=-1) 

sản lượng này:

   value  
item  item 1 item 2 
year month    
2004 1   21 277 
    2   43 244 
    3   12 262 
    4   80 201 
    5   22 287 
    6   52 284 
    7   90 249 
    8   14 229 
    9   52 205 
    10  76 207 
    11  88 259 
    12  90 200 

Nhanh hơn một chút so với việc sử dụng pivot_table và tốc độ tương tự hoặc chậm hơn một chút so với sử dụng groupby.

+0

Bạn cũng có thể tham khảo cấp chỉ mục trực tiếp, ví dụ: df.set_index (['năm', 'tháng', 'mục']). unstack ('fcode'). Phương pháp đầu tiên của Alexander trong câu trả lời của ông cũng sẽ thất bại với dữ liệu phi số (trong một vấn đề tổng quát hơn so với một ở đây). – Carl

+0

đây là một câu trả lời tuyệt vời. –

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