2013-02-01 849 views
6

tôi đang gặp phải một số sự cố khi che mặt bảng theo cách tương tự như cách tôi tạo Khung dữ liệu. Những gì tôi muốn làm cảm thấy đơn giản, nhưng tôi đã không tìm thấy một cách nhìn vào các tài liệu và diễn đàn trực tuyến. Tôi có một ví dụ đơn giản dưới đây:mặt nạ boolean trong bảng điều khiển gấu trúc

import pandas 
import numpy as np 
import datetime 
start_date = datetime.datetime(2009,3,1,6,29,59) 
r = pandas.date_range(start_date, periods=12) 
cols_1 = ['AAPL', 'AAPL', 'GOOG', 'GOOG', 'GS', 'GS'] 
cols_2 = ['close', 'rate', 'close', 'rate', 'close', 'rate'] 
dat = np.random.randn(12, 6) 

dftst = pandas.DataFrame(dat, columns=pandas.MultiIndex.from_arrays([cols_1, cols_2], names=['ticker','field']), index=r) 
pn = dftst.T.to_panel().transpose(2,0,1) 
print pn 

Out[14]: 
<class 'pandas.core.panel.Panel'> 
Dimensions: 2 (items) x 12 (major_axis) x 3 (minor_axis) 
Items axis: close to rate 
Major_axis axis: 2009-03-01 06:29:59 to 2009-03-12 06:29:59 
Minor_axis axis: AAPL to GS 

bây giờ tôi có một đối tượng Panel, nếu tôi mất một lát dọc theo trục mục, tôi nhận được một DataFrame

close_p = pn['close'] 
print close_p 

Out[16]: 
ticker     AAPL  GOOG  GS 
2009-03-01 06:29:59 -0.082203 -0.286354 1.227193 
2009-03-02 06:29:59 0.340005 -0.688933 -1.505137 
2009-03-03 06:29:59 -0.525567 0.321858 -0.035047 
2009-03-04 06:29:59 -0.123549 -0.841781 -0.616523 
2009-03-05 06:29:59 -0.407504 0.188372 1.311262 
2009-03-06 06:29:59 0.272883 0.817179 0.584664 
2009-03-07 06:29:59 -1.767227 1.168876 0.443096 
2009-03-08 06:29:59 -0.685501 -0.534373 -0.063906 
2009-03-09 06:29:59 0.851820 0.068740 0.566537 
2009-03-10 06:29:59 0.390678 -0.012422 -0.152375 
2009-03-11 06:29:59 -0.985585 -0.917705 -0.585091 
2009-03-12 06:29:59 0.067498 -0.764343 0.497270 

Tôi có thể lọc dữ liệu này theo hai cách :

1) tôi tạo ra một mặt nạ và mặt nạ dữ liệu như sau:

msk = close_p > 0 
close_p = close_p.mask(msk) 

2) tôi chỉ có thể cắt bởi các op boolean erator in msk above

close_p = close_p[close_p > 0] 
Out[28]: 
ticker     AAPL  GOOG  GS 
2009-03-01 06:29:59  NaN  NaN 1.227193 
2009-03-02 06:29:59 0.340005  NaN  NaN 
2009-03-03 06:29:59  NaN 0.321858  NaN 
2009-03-04 06:29:59  NaN  NaN  NaN 
2009-03-05 06:29:59  NaN 0.188372 1.311262 
2009-03-06 06:29:59 0.272883 0.817179 0.584664 
2009-03-07 06:29:59  NaN 1.168876 0.443096 
2009-03-08 06:29:59  NaN  NaN  NaN 
2009-03-09 06:29:59 0.851820 0.068740 0.566537 
2009-03-10 06:29:59 0.390678  NaN  NaN 
2009-03-11 06:29:59  NaN  NaN  NaN 
2009-03-12 06:29:59 0.067498  NaN 0.497270 

Điều tôi không thể biết là làm thế nào để lọc tất cả dữ liệu của mình dựa trên mặt nạ không có vòng lặp. Tôi có thể thực hiện các thao tác sau:

msk = (pn['rate'] > 0) & (pn['close'] > 0) 
def mask_panel(pan, msk): 
    for item in pan.items: 
     pan[item] = pan[item].mask(msk) 
    return pan 
print pn['close'] 

Out[32]: 
ticker     AAPL  GOOG  GS 
2009-03-01 06:29:59 -0.082203 -0.286354 1.227193 
2009-03-02 06:29:59 0.340005 -0.688933 -1.505137 
2009-03-03 06:29:59 -0.525567 0.321858 -0.035047 
2009-03-04 06:29:59 -0.123549 -0.841781 -0.616523 
2009-03-05 06:29:59 -0.407504 0.188372 1.311262 
2009-03-06 06:29:59 0.272883 0.817179 0.584664 
2009-03-07 06:29:59 -1.767227 1.168876 0.443096 
2009-03-08 06:29:59 -0.685501 -0.534373 -0.063906 
2009-03-09 06:29:59 0.851820 0.068740 0.566537 
2009-03-10 06:29:59 0.390678 -0.012422 -0.152375 
2009-03-11 06:29:59 -0.985585 -0.917705 -0.585091 
2009-03-12 06:29:59 0.067498 -0.764343 0.497270 

mask_panel(pn, msk) 

print pn['close'] 

Out[34]: 
ticker     AAPL  GOOG  GS 
2009-03-01 06:29:59 -0.082203 -0.286354  NaN 
2009-03-02 06:29:59  NaN -0.688933 -1.505137 
2009-03-03 06:29:59 -0.525567  NaN -0.035047 
2009-03-04 06:29:59 -0.123549 -0.841781 -0.616523 
2009-03-05 06:29:59 -0.407504  NaN  NaN 
2009-03-06 06:29:59  NaN  NaN  NaN 
2009-03-07 06:29:59 -1.767227  NaN  NaN 
2009-03-08 06:29:59 -0.685501 -0.534373 -0.063906 
2009-03-09 06:29:59  NaN  NaN  NaN 
2009-03-10 06:29:59  NaN -0.012422 -0.152375 
2009-03-11 06:29:59 -0.985585 -0.917705 -0.585091 
2009-03-12 06:29:59  NaN -0.764343  NaN 

Vì vậy, vòng lặp ở trên thực hiện thủ thuật. Tôi biết có một cách vectorized nhanh hơn để làm điều này bằng cách sử dụng ndarray, nhưng tôi đã không đặt rằng với nhau được nêu ra. Nó cũng có vẻ như đây nên là chức năng được xây dựng trong thư viện gấu trúc. Nếu có một cách để làm điều này mà tôi đang thiếu, bất kỳ lời đề nghị sẽ được nhiều đánh giá cao.

+0

Nó cảm thấy như bạn nên để có thể để sử dụng bảng boolean 'pn.gt (0)' ... –

+0

cảm ơn Andy, trừ khi tôi sai, tôi nghĩ rằng sẽ làm điều gì đó khác. Điều đó sẽ nan ra mỗi DataFrame trong bảng điều khiển của tôi, nơi các giá trị của nó là ít hơn 0. Những gì tôi muốn làm là nan ra mỗi DataFrame trong Panel của tôi, nơi 'gần' là ít hơn 0. Một lần nữa, đóng là một DataFrame cụ thể trong Panel của tôi . Tôi sẽ không quan tâm và đăng bài nếu tôi nghĩ ra điều gì đó đẹp hơn. – granders19

+0

Điều đó chỉ ảnh hưởng đến khung dữ liệu đóng (một phần của bảng điều khiển) không? Bạn có muốn thay đổi điều đó trong bảng điều khiển và để người khác không thay đổi? –

Trả lời

9

Tôi nghĩ rằng điều này sẽ làm việc (và những gì Panel.where nên làm, nhưng một chút của nó không tầm thường vì nó có để xử lý một loạt các trường hợp)

# construct the mask in 2-d (a frame) 
In [36]: mask = (pn['close']>0) & (pn['rate']>0) 

In [37]: mask 
Out[37]: 
ticker    AAPL GOOG  GS 
2009-03-01 06:29:59 False False False 
2009-03-02 06:29:59 False False True 
.... 

# here's the key, this broadcasts, setting the values which 
# don't meet the condition to nan 
In [38]: masked_values = np.where(mask,pn.values,np.nan) 

# reconstruct the panel (the _construct_axes_dict is an internal function that returns 
# dict of the axes, e.g. items -> the items, major_axis -> ..... 
In [42]: x = pd.Panel(masked_values,**pn._construct_axes_dict()) 
Out[42]: 
<class 'pandas.core.panel.Panel'> 
Dimensions: 2 (items) x 12 (major_axis) x 3 (minor_axis) 
Items axis: close to rate 
Major_axis axis: 2009-03-01 06:29:59 to 2009-03-12 06:29:59 
Minor_axis axis: AAPL to GS 

# the values 
In [43]: x 
Out[43]: 
array([[[  nan,   nan,   nan], 
    [  nan,   nan, 0.09575723], 
    [  nan,   nan,   nan], 
    [  nan,   nan,   nan], 
    [  nan, 2.07229823, 0.04347515], 
    [  nan,   nan,   nan], 
    [  nan,   nan, 2.18342239], 
    [  nan,   nan, 1.73674381], 
    [  nan, 2.01173087,   nan], 
    [ 0.24109645, 0.94583072,   nan], 
    [ 0.36953467,   nan, 0.18044432], 
    [ 1.74164222, 1.02314752, 1.73736033]], 

    [[  nan,   nan,   nan], 
    [  nan,   nan, 0.06960387], 
    [  nan,   nan,   nan], 
    [  nan,   nan,   nan], 
    [  nan, 0.63202199, 0.56724391], 
    [  nan,   nan,   nan], 
    [  nan,   nan, 0.71964824], 
    [  nan,   nan, 1.03482927], 
    [  nan, 0.18256148,   nan], 
    [ 1.29451667, 0.49804327,   nan], 
    [ 2.04726538,   nan, 0.12883128], 
    [ 0.70647885, 0.7277734 , 0.77844475]]]) 
+0

cảm ơn Jeff, điều đó đã hiệu quả! nó là một giải pháp tốt hơn so với vòng lặp tôi đã đưa ra. Tôi đồng ý rằng nó sẽ được tốt đẹp nếu điều này đã được xây dựng thành một phương pháp. – granders19

+0

không có prob - sẽ nhận được nó tại một số điểm https://github.com/pydata/pandas/issues/2790 – Jeff