我可以使用布尔掩码来查找 DateTime 值是否位于不同数据帧中的其他两个 DateTime 值之间

Can I use a boolean mask to find if a DateTime value falls between two other DateTime values in a different dataframe

提问人:Marloes 提问时间:6/19/2023 最后编辑:Marloes 更新时间:6/19/2023 访问量:30

问:

我想过滤我拥有的数据点,直到我只剩下参与者睡着的数据点。我有我的 DataFrame,其中包含 DateTime 值和我正在研究的值,以及一个不同的 DataFrame,该数据 Frame 包含参与者开始睡眠和结束睡眠的时间。我不想在布尔掩码中写出每个开始和停止时间,而是想知道是否有一种方法可以通过遍历大数据帧或具有开始和结束睡眠时间的数据帧来做到这一点,或者比手动输入 175 个晚上更好的方法。

开始/停止数据帧如下所示,我为每个参与者都有一个:

df_sleep1:

date            start       stop
5/30/2023   5/29/2023 22:15 5/30/2023 7:22
5/31/2023   5/30/2023 23:19 5/31/2023 6:46
6/1/2023    6/1/2023 0:02   6/1/2023 8:31

包含所有数据的数据帧如下所示,我想在其中添加一个“睡眠”列:

DF:

        DateTime            HeartRate        Participant      Asleep
0   2023-05-29 23:44:00 76.0             1
1   2023-05-30 06:44:00 76.0             1
2   2023-05-30 20:45:00 84.0             1
3   2023-05-31 04:45:00 84.0             2
4   2023-06-1 20:46:00  81.0             2

我尝试过什么:

dt = df['DateTime'].to_numpy()

start1 = df_sleep1['Start'].to_numpy()[:, None]
end1 = df_sleep1['Stop'].to_numpy()[:, None]
    
mask1 = ((start1 <= dt) & (dt <= end1) & (df['Participant'] == 1))
df['Sleep'] = mask1.any(axis=0)
def sleepFunction(row):
    if (df_sleep1['Start'] <= dt) & (dt <= df_sleep1['Stop']) & (df['Participant'] == 1):
        return True
    else:
        return False

df['sleepState'] = df.apply(lambda row: sleepFunction(row), axis = 1)

两者都给出了关于数据帧/数组形状不匹配的类似错误,这无论如何都不是我想做的事情。

pandas datetime jupyter-notebook 布尔表达式

评论

0赞 mozway 6/19/2023
范围是否不重叠?df_sleep1
0赞 mozway 6/19/2023
另外,每个参与者都有一个吗?df_sleepX
0赞 Marloes 6/19/2023
@mozway是的,是的
0赞 mozway 6/19/2023
谢谢,那么 A 应该可以正常工作,见下文merge_asof

答:

0赞 mozway 6/19/2023 #1

如果间隔不重叠,则有效的方法是使用merge_asof:按参与者合并开始日期,然后确保日期在结束日期之后。

# map the Participant ID to the df_sleep DataFrame
all_sleep = pd.concat({1: df_sleep1}, names=['Participant']).reset_index(level=0)

# ensure having datetime types
all_sleep[['start', 'stop']] = all_sleep[['start', 'stop']].apply(pd.to_datetime)
df['DateTime'] = pd.to_datetime(df['DateTime'])

# merge by date and participant
df['Asleep'] = (
 pd.merge_asof(df.sort_values(by='DateTime').reset_index(),
               all_sleep.sort_values(by='start'),
               left_on='DateTime', right_on='start',
               by='Participant'
              )
   .assign(Asleep=lambda d: d['DateTime'].le(d['stop']))
   .set_index('index')['Asleep']
)

输出:

             DateTime  HeartRate  Participant  Asleep
0 2023-05-29 23:44:00       76.0            1    True
1 2023-05-30 06:44:00       76.0            1    True
2 2023-05-30 20:45:00       84.0            1   False
3 2023-05-31 04:45:00       84.0            2   False
4 2023-06-01 20:46:00       81.0            2   False

评论

0赞 Marloes 6/19/2023
这适用于 1 个参与者,但是由于多个参与者和多个开始睡眠和停止睡眠时间存在一些重叠,这使它们都位于同一数据帧中
0赞 mozway 6/19/2023
@Marloes你能提供一个可重复的例子?应由参与者决定。merge_asof
0赞 Marloes 6/19/2023
也许我做错了什么,我应该如何添加其他参与者?
0赞 mozway 6/19/2023
你说你有更多的数据帧,你能提供吗?您应该将它们添加到字典中:df_sleep2{1: df_sleep1, 2: df_sleep2}
1赞 Marloes 6/19/2023
我以为这就是我所做的,但它现在正在起作用!非常感谢!