Python 在数据帧中选择时间窗口

Python 在数据帧中选择时间窗口,python,pandas,dataframe,time-series,Python,Pandas,Dataframe,Time Series,我有一个数据帧,df,看起来像这样: HeartRate_smooth 2018-01-01 00:07:00 58.000000 2018-01-01 00:13:00 59.333333 2018-01-01 00:14:00 57.333333 2018-01-01 00:20:00 59.333333 2018-01-01 00:21:00 59.333333 2018-01-01 00:22:00 57.333333 2018-01

我有一个数据帧,df,看起来像这样:

                     HeartRate_smooth
2018-01-01 00:07:00  58.000000
2018-01-01 00:13:00  59.333333
2018-01-01 00:14:00  57.333333
2018-01-01 00:20:00  59.333333
2018-01-01 00:21:00  59.333333
2018-01-01 00:22:00  57.333333
2018-01-01 00:34:00  59.666667
2018-01-01 00:36:00  58.666667
2018-01-01 00:37:00  57.666667
2018-01-01 00:38:00  55.000000
2018-01-01 00:39:00  58.333333
2018-01-01 01:03:00  57.666667
2018-01-01 01:08:00  59.666667
2018-01-01 01:09:00  56.333333
2018-01-01 01:10:00  54.666667
2018-01-01 01:32:00  59.666667
2018-01-01 01:33:00  57.000000
2018-01-01 01:34:00  54.333333
2018-01-01 01:56:00  56.000000
2018-01-01 01:57:00  58.000000
2018-01-01 01:58:00  59.000000
2018-01-01 02:03:00  59.666667
2018-01-01 02:07:00  58.666667
2018-01-01 03:00:00  59.666667
2018-01-01 03:09:00  59.333333
2018-01-01 03:10:00  58.333333
2018-01-01 03:31:00  58.666667
2018-01-01 10:46:00  59.666667
2018-01-01 12:40:00  58.333333
2018-01-01 14:42:00  59.000000
此数据帧是患者心率低于阈值时的时间点集合。我假设这些时间点要么是患者休息时,要么是睡眠时。我试图找出我可以识别患者睡眠时间的地方。我假设在一个时间段的每一行之间的间隔不到30分钟的情况下,当存在超过一小时的数据时,患者处于睡眠状态

在给定的数据帧中,我可以假设患者在00:07到02:07之间睡觉。这是因为从00:07到02:07,每行之间缺少的数据少于30分钟。02:07之后的那一排时间差超过30分钟,因此我假设患者已经醒了

请注意,我将循环浏览多个患者数据,患者的睡眠时间将有所不同。它可能并不总是从数据帧中的第一个条目开始

我的问题是:
1.我如何识别患者处于睡眠状态的时间段并将当前数据帧分为2个,其中一个dfs用于在患者处于睡眠状态时存储数据,另一个用于在患者处于清醒状态时存储数据?
2.这不是必需的,但如果可能,我如何打印患者睡眠的时间和时间量

基于提供的样本数据框的样本数据输出:
(小标题)

                     HeartRate_smooth
2018-01-01 00:07:00  58.000000
2018-01-01 00:13:00  59.333333
2018-01-01 00:14:00  57.333333
2018-01-01 00:20:00  59.333333
2018-01-01 00:21:00  59.333333
2018-01-01 00:22:00  57.333333
2018-01-01 00:34:00  59.666667
2018-01-01 00:36:00  58.666667
2018-01-01 00:37:00  57.666667
2018-01-01 00:38:00  55.000000
2018-01-01 00:39:00  58.333333
2018-01-01 01:03:00  57.666667
2018-01-01 01:08:00  59.666667
2018-01-01 01:09:00  56.333333
2018-01-01 01:10:00  54.666667
2018-01-01 01:32:00  59.666667
2018-01-01 01:33:00  57.000000
2018-01-01 01:34:00  54.333333
2018-01-01 01:56:00  56.000000
2018-01-01 01:57:00  58.000000
2018-01-01 01:58:00  59.000000
2018-01-01 02:03:00  59.666667
2018-01-01 02:07:00  58.666667
苏醒(df):

                     HeartRate_smooth
2018-01-01 03:00:00  59.666667
2018-01-01 03:09:00  59.333333
2018-01-01 03:10:00  58.333333
2018-01-01 03:31:00  58.666667
2018-01-01 10:46:00  59.666667
2018-01-01 12:40:00  58.333333
2018-01-01 14:42:00  59.000000

“患者从00:07睡到03:31睡了3小时24分钟”

我发现处理时间更容易,而不是索引:

df.reset_index(inplace=True)

# df now has a timestamp column named 'index'

# difference with previous row larger than 30 mins
# cumsum for consecutive block:
df['block'] = df['index'].diff().dt.seconds.ge(30*60).cumsum()

# all sleep chunks
awake_df = (df.set_index('index')
              .groupby('block')[['HeartRate_smooth']]
              .apply(lambda x: x if len(x) > 1 else None)
           )
输出
awake\u df

+--------+----------------------+-------------------+
|        |                      | HeartRate_smooth  |
+--------+----------------------+-------------------+
| block  | index                |                   |
+--------+----------------------+-------------------+    
| 0      | 2018-01-01 00:07:00  | 58.000000         |
|        | 2018-01-01 00:13:00  | 59.333333         |
|        | 2018-01-01 00:14:00  | 57.333333         |
|        | 2018-01-01 00:20:00  | 59.333333         |
|        | 2018-01-01 00:21:00  | 59.333333         |
|        | 2018-01-01 00:22:00  | 57.333333         |
|        | 2018-01-01 00:34:00  | 59.666667         |
|        | 2018-01-01 00:36:00  | 58.666667         |
|        | 2018-01-01 00:37:00  | 57.666667         |
|        | 2018-01-01 00:38:00  | 55.000000         |
|        | 2018-01-01 00:39:00  | 58.333333         |
|        | 2018-01-01 01:03:00  | 57.666667         |
|        | 2018-01-01 01:08:00  | 59.666667         |
|        | 2018-01-01 01:09:00  | 56.333333         |
|        | 2018-01-01 01:10:00  | 54.666667         |
|        | 2018-01-01 01:32:00  | 59.666667         |
|        | 2018-01-01 01:33:00  | 57.000000         |
|        | 2018-01-01 01:34:00  | 54.333333         |
|        | 2018-01-01 01:56:00  | 56.000000         |
|        | 2018-01-01 01:57:00  | 58.000000         |
|        | 2018-01-01 01:58:00  | 59.000000         |
|        | 2018-01-01 02:03:00  | 59.666667         |
|        | 2018-01-01 02:07:00  | 58.666667         |
| 1      | 2018-01-01 03:00:00  | 59.666667         |
|        | 2018-01-01 03:09:00  | 59.333333         |
|        | 2018-01-01 03:10:00  | 58.333333         |
|        | 2018-01-01 03:31:00  | 58.666667         |
+--------+----------------------+-------------------+  
请注意,有两个睡眠区块,因为您的数据实际上在
02:07
03:00
之间有53分钟的间隔。为了获得睡眠时间:

(awake_df.reset_index(level=1)
         .groupby('block')['index']
         .apply(lambda x: x.max()-x.min())
)
给出:

block
0     02:00:00
1     00:22:00
Name: index, dtype: timedelta64[ns]

请发布您解决此问题的尝试。
02:07
03:00
@QuangHoang之间实际上有53分钟的间隔。谢谢您指出这一点。我已经编辑了我的问题。嗨,非常感谢你的回答。请解释一下
.apply(lambda x:x,如果len(x)>1,其他任何一行都不
能做什么?谢谢!
len(x)=1
表示该行比前一行晚30分钟以上,比下一行早30分钟以上。您可以尝试
lambda x:x
并查看打印的内容。这将帮助您更好地理解它。