python - 将熊猫数据框过滤为仅在两个日期之间处于活动状态的记录的 Pythonic 方法
问题描述
这是我反复遇到的事情,我想知道是否有比我正在做的更简单的方法来做到这一点。为了说明,这是一个人为的例子。
我有一个熊猫数据框。这是一些机器何时启动和关闭的日志:
| MachineID | StartDate | EndDate |
|-----------|------------|------------|
| 1 | 2020-01-01 | 2020-06-01 |
| 2 | 2020-01-01 | 2020-02-01 |
| 3 | 2020-03-01 | 2020-07-15 |
| 4 | 2020-04-01 | 2020-05-01 |
| 5 | 2020-04-01 | 2020-07-15 |
| 6 | 2020-05-01 | |
| 7 | 2020-07-01 | |
EndDate 列中的空值表示机器尚未关闭。日期可以是任何一天,为了简单起见,我只使用了第一个。
现在说我想将数据框过滤到仅在两个日期之间的任何时间处于活动状态的机器,在这种情况下,假设活动期间的开始日期是 2020-04-01,结束日期是 2020-06-30 .
start end
2020-04-01 2020-06-30
| |
Machine 1 xxxxxxxxxxxxxxxxxxxxxxxx
Machine 2 xxx
Machine 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Machine 4 xxxxxxxxxxxxxxxxxx
Machine 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Machine 6 xxxxxxxxxxxxxxxxxxx...(still going)
Machine 7 xxxxxxxxxx...(still going)
| |
如果我只使用(df["StartDate"]>=start) & (df["EndDate"]<=end)
我会过滤掉我绝对不想要的机器 3 和 6,因为它们在此期间处于活动状态。我刚才正在做的是构建一个非常冗长的过滤器,如下所示:
start = "2020-04-01"
end = "2020-06-30"
dff = df[
# Machines that started before the start date
((df["StartDate"]<=start) & ((df["EndDate"]>=start) & (df["End date"] <= end))) | \
((df["StartDate"]<=start) & (df["EndDate"]>=end)) | \
((df["StartDate"]<=start) & (df["EndDate"].isnull())) | \
# Machines that started after the start date
((df["StartDate"]>=start) & ((df["EndDate"]>=start) & (df["End date"] <= end))) | \
((df["StartDate"]>=start) & (df["EndDate"]>=end)) | \
((df["StartDate"]>=start) & (df["EndDate"].isnull()))
]
这似乎可以完成工作,但必须有更好的方法。如果有人关心可以提供替代方案,我已经完全准备好面对一些明显的事情(我对此很陌生)?
解决方案
我学到的一个技巧是翻转比较:比较一个范围的开始与另一个范围的结束,反之亦然:
start = pd.Timestamp('2020-04-01')
end = pd.Timestamp('2020-06-30')
cond = (df['StartDate'] < end) & (df['EndDate'].fillna(pd.Timestamp('2099-01-01')) > start)
dff = df[cond]
如果你反复使用这个,把它变成一个函数。
推荐阅读
- ios - IOS/Objective-C:在barbutton中同时显示两个图像
- c# - 在 Linux Python 中使用 .NET Core 库
- groovy - Groovy 2.5 Java 10 和 sparkjava
- hadoop - hadoop 运行示例 输入路径不存在
- docker - Docker 工具箱:来自守护进程的错误响应:无效模式:/root/docker
- javascript - 我在 AWS 上托管的 Web 应用程序的一些脚本和页面正在以某种方式被修改
- android - 长按刷新列表后取消ListView上的点击事件
- hibernate - Java spring Boot,JPA,Hibernate,持久化 OBJECT 类型的对象
- r - 异常化r包错误
- android - 使用 rxjava2 遍历列表