You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于睡眠时长占比将DateTime睡眠数据的mixed类别转为day/night?

解决睡眠数据跨时段分类的问题

我来帮你搞定这个把"mixed"睡眠时段按占比重新分类的需求!咱们一步步来:

首先,核心思路是计算每个睡眠时段在白天(8:00-20:00)和夜间(20:00-次日8:00)的实际时长占比,然后把原来标记为"mixed"的记录替换为占比更高的类别。

第一步:定义计算重叠时长的函数

我们需要一个函数来计算单个睡眠时段和白天/夜间区间的重叠时长,这里用lubridate的时间区间工具来实现:

library(tidyverse)
library(lubridate)

# 计算睡眠时段在白天和夜间的时长(分钟)
calc_day_night_duration <- function(start_time, end_time) {
  # 获取睡眠覆盖的所有日期
  dates <- seq.Date(as.Date(start_time), as.Date(end_time), by = "day")
  
  day_total <- 0
  night_total <- 0
  
  for (date in dates) {
    # 当天白天区间:8:00 - 20:00
    day_int <- interval(ymd_hms(paste(date, "08:00:00")), ymd_hms(paste(date, "20:00:00")))
    # 当天夜间区间:20:00 - 次日8:00
    night_int <- interval(ymd_hms(paste(date, "20:00:00")), ymd_hms(paste(date + 1, "08:00:00")))
    
    # 计算和白天区间的重叠时长
    day_overlap <- intersect(interval(start_time, end_time), day_int)
    if (!is.na(day_overlap)) day_total <- day_total + as.numeric(as.duration(day_overlap), "minutes")
    
    # 计算和夜间区间的重叠时长
    night_overlap <- intersect(interval(start_time, end_time), night_int)
    if (!is.na(night_overlap)) night_total <- night_total + as.numeric(as.duration(night_overlap), "minutes")
  }
  
  tibble(day_minutes = day_total, night_minutes = night_total)
}

第二步:整合到数据处理流程里

接下来把这个函数和你原来的分类逻辑结合,替换"mixed"类别:

# 你的原始数据
mydata <- data.frame(
  id = c("m1","m1","m1","m2","m2","m2","m3","m4","m4"),
  start = strptime(c("2020-01-03 10:00:00","2020-01-03 16:00:00","2020-01-03 19:20:00","2020-01-05 10:00:00","2020-01-05 15:20:00","2020-01-05 20:50:00","2020-01-06 06:30:00","2020-01-08 06:30:00","2020-01-08 07:50:00"), "%Y-%m-%d %H:%M:%S"),
  end = strptime(c("2020-01-03 16:00:00","2020-01-03 19:20:00","2020-01-03 20:50:00","2020-01-05 15:20:00","2020-01-05 20:50:00","2020-01-05 22:00:00","2020-01-06 07:40:00","2020-01-08 07:50:00","2020-01-08 08:55:00"), "%Y-%m-%d %H:%M:%S")
)

# 最终数据处理流程
df_final <- mydata %>%
  # 转换时间格式为ymd_hms
  mutate_at(vars(start, end), ymd_hms) %>%
  # 先标记初始的day/night/mixed类别
  mutate(
    start_hour = hour(start),
    end_hour = hour(end),
    day.night_initial = case_when(
      start_hour >= 8 & end_hour >= 8 & end_hour < 20 ~ "day",
      start_hour >= 20 & (end_hour < 8 | end_hour <= 23) | (start_hour < 8 & end_hour < 8) ~ "night",
      TRUE ~ "mixed"
    )
  ) %>%
  # 逐行计算白天/夜间时长
  rowwise() %>%
  mutate(calc_day_night_duration(start, end)) %>%
  ungroup() %>%
  # 根据时长占比替换mixed类别
  mutate(
    day.night = case_when(
      day.night_initial != "mixed" ~ day.night_initial,
      day_minutes > night_minutes ~ "day",
      night_minutes > day_minutes ~ "night",
      # 如果时长相等,这里默认设为night,你可以根据需求调整
      TRUE ~ "night"
    )
  ) %>%
  # 清理中间列(可选)
  select(-start_hour, -end_hour, -day.night_initial)

第三步:验证结果

运行后你会看到:

  • 第3行(19:20-20:50):白天40分钟,夜间50分钟 → 转为night
  • 第5行(15:20-20:50):白天280分钟,夜间50分钟 → 转为day
  • 第9行(07:50-08:55):白天55分钟,夜间10分钟 → 转为day

完全符合你的需求!如果需要调整时长相等时的规则,直接修改最后一个TRUE ~ "night"即可。

内容的提问来源于stack exchange,提问作者Sparky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:23:55