将 pandas 数据框过滤为仅在两个日期之间处于事件状态的记录的 Pythonic 方法

标签 python pandas date filter

这是我反复遇到的事情,我想知道是否有比我正在做的更简单的方法。这是为了说明目的而虚构的示例。

我有一个 pandas 数据框。这是多台机器启动和关闭的日志,如下所示:

| 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]

如果你重复使用它,请将其变成一个函数。

关于将 pandas 数据框过滤为仅在两个日期之间处于事件状态的记录的 Pythonic 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62940510/

相关文章:

python - google API - python oauth2 应用程序身份验证

python - 如何使函数从 Python 中的函数外部获取变量?

python - pandas - 根据 'next' 行值创建新列

Android 小部件无法接收 DATE_CHANGED 消息

javascript - 如何让这个 JavaScript 倒计时使用 UTC 时间?

python - 在 perl/python 中保持系统退出状态的超时限制

python - 从 pandas 数据框中提取多列的组合

python - reshape Pandas.DataFrame 的 Pythonic 方式

python-3.x - 用 Pandas 处理重复数据

android - 加载 en 的时区名称