【问题标题】:Selecting time-window in a dataframe在数据框中选择时间窗口
【发布时间】:2019-10-03 06:06:19
【问题描述】:

我有一个数据框 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.这不是必须的,但如果可能的话,我怎样才能打印出患者入睡的时间和时间?

基于提供的示例数据框的示例数据输出:
睡眠_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

Awake_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 分钟”

【问题讨论】:

  • 请发表您解决此问题的尝试。
  • 02:0703:00 之间实际上有 53 分钟的差距
  • @QuangHoang 感谢您指出这一点。我已经编辑了我的问题。

标签: python pandas dataframe time-series


【解决方案1】:

我发现处理非索引时间更容易:

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_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:0703: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]

【讨论】:

  • 您好,非常感谢您的回答。你能解释一下.apply(lambda x: x if len(x) > 1 else None 的作用吗?谢谢!
  • len(x)=1 表示该行比上一行晚 30 分钟以上,比下一行早 30 分钟以上。你可以试试lambda x: x 看看打印了什么。这将帮助您更好地理解它。
猜你喜欢
  • 2020-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多