首页 > 解决方案 > 熊猫多索引,删除条件仍然成立的行?

问题描述

我有一个多级数据框

                          Buy     Sell
Date       Time                       
2018-01-03 11:36:00  24380.50      0.0
           11:37:00  24392.55      0.0
           11:38:00  24392.80      0.0
           11:39:00  24383.90      0.0
           11:48:00  24379.95      0.0
           11:49:00  24393.55      0.0
           11:50:00  24391.55      0.0
           11:51:00  24394.30      0.0
           11:52:00  24391.40      0.0
           11:53:00  24397.20      0.0
           11:54:00  24407.45      0.0
           11:55:00  24404.15      0.0
           11:56:00  24401.95      0.0
           11:57:00  24395.90      0.0
           12:29:00  24387.60      0.0
           12:31:00  24390.45      0.0
           12:33:00  24393.80      0.0
           12:34:00  24397.60      0.0
           12:36:00  24391.95      0.0
           12:37:00  24401.35      0.0
           12:38:00  0.0           24408.50
           12:39:00  24412.35      0.0
           12:40:00  24418.60      0.0
           12:41:00  24426.00      0.0
           12:42:00  24425.00      0.0
           12:43:00  24419.80      0.0
           13:36:00  24390.35      0.0
           13:43:00  0.0           24394.60
           13:44:00  0.0           24397.90
           13:45:00  0.0           24395.85

我在尝试着:

如果Buy > 0,则丢弃它之后的所有值 where Buy > 0 & Sell == 0,如果Sell>0然后将该Sell值获取到第一个所在的Buy位置。

并开始丢弃下一个值 whereSell>0并找到下一个Buy > 0.. 以此类推。

如果Date' 水平没有更多观察结果,则将最后一个观察结果作为买入/卖出取决于最后一个观察结果

预期输出:

                      Buy     Sell      CloseTime  CloseDate
Date       Time                       
2018-01-03 11:36:00  24380.50     24408.50   12:38:00  2018-01-03
           12:38:00  24395.85     24412.35  12:39:00  2018-01-03 
           12:39:00  24395.85     24394.60  13:43:00  2018-01-03
           13:43:00  24394.60     24395.85  13:45:00 2018-01-03 # Last obs.

到目前为止我尝试过的事情:

df[(df['Buy'] > 0) & (df['Buy'].shift(-1)>0),'Sell'] = 1

然后通过检查 1 是否存在来删除。

它对我没有多大帮助,因为即使第一行也得到了 1。

我也尝试了一个 for 循环,但这并没有多大帮助,虽然我可以在那里看到一种方法,但这会非常浪费。

标签: pythonpandas

解决方案


我的解决方案有点不同 - 添加一个新的 col 和drop_duplicates

df['buyorsell'] = np.where(df['Buy']>0, 'B', 'S')
df.drop_duplicates(subset='buyorsell', keep='first').iloc[:,:-1]

Time            Buy     Sell
11:36:00    24380.5     0.0
13:43:00    0.0     24394.6

(我省略了多索引,但它应该是相同的。)

不过,这只会给你第一个改变。要获得每个更改,请将第二行交换为:

df.loc[df['buyorsell']shift(-1) != df['buyorsell']].iloc[:,:-1]

并且要重新创建所需输出的 ​​, ,您可以简单地使用CloseTime,将 Date 和 Time 既作为索引又作为单独的列。CloseDate.reset_index().set_index(['Date', 'Time'], drop=False)

在聊天中讨论之后,我们发现我们需要获取每天的第一条和最后一条记录,以及每次更改,所以最终的答案是:

df.groupby('Date', group_keys=False).apply(lambda df: pd.concat([df.iloc[[0, -1]], df[df.buyorsell.shift().ne(df.buyorsell)]]).drop_duplicates().sort_index())

要保留每天没有变化的最后一个条目,您可以将其放在一个函数中并使用apply

def find_day(df):
    if df.buyorsell.nunique() == 1:
        return df.drop_duplicates(subset=['buyorsell'], keep='last')
    return df[df.buyorsell.shift() != df.buyorsell].iloc[:,:-1]

df.groupby('date').apply(find_day)

推荐阅读