python - 熊猫多索引,删除条件仍然成立的行?
问题描述
我有一个多级数据框
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 循环,但这并没有多大帮助,虽然我可以在那里看到一种方法,但这会非常浪费。
解决方案
我的解决方案有点不同 - 添加一个新的 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)
推荐阅读
- java - Zip4j 无法删除或覆盖文件内的文件
- android - 如何在正确的时间调用方法?
- flutter - 使用 maxLength 和 Flutter TextField
- python - 从文本文件创建元组
- java - 为什么我得到一个“mergeCursor”对象而不是一个“字符串”?
- azure - 能够 ping 到某个 IP,但无法从 Azure vm 浏览该 IP
- android - 条件语句选择图像时出现 Kotlin 错误
- python - Django json响应中的数据操作
- c# - 如何使用 Serilog 在 Json 中获取日志级别 - .NET Core 3.1
- digital-ocean - ERPNEXT 安装错误“Procfile 不存在”