R语言中匹配EMA触发时间与传感器唤醒时间的格式问题求助
我有传感器数据和生态瞬时评估(EMA)应用数据,两类数据均在4天内分2个时间点采集。传感器需全天佩戴(含睡眠时段),可获取睡眠(1)、清醒(0)或未佩戴状态;参与者醒来后需立即点击EMA应用按钮,因此有两类唤醒时间数据。因传感器数据更客观,我希望以其作为唤醒时间指标,现需匹配每日首个EMA触发时间对应的最近传感器唤醒时间,但在R中处理时,结果列显示为时间戳而非预期的日期时间格式。
已执行步骤及问题现象
提取传感器客观唤醒时间:
从传感器数据中提取睡眠转清醒的时间,得到POSIXct向量:library(dplyr) data$Time <- as.POSIXct(data$Time, format = "%Y-%m-%d %H:%M:%S", tz = "UTC") wake_up_rows <- which(data$SleepWakeWear == 0 & lag(data$SleepWakeWear) == 1) wake_up_times <- data$Time[wake_up_rows]最终得到的POSIXct向量结构如下:
wake_up_times <- structure(c(1513387680, 1513398780, 1513407000, 1513470900, 1513473180, 1513487820, 1513492560, 1513551420, 1513555740, 1513563180, 1513574940, 1513615500, 1513639080, 1513649280, 1513652760, 1513664280, 1513667520, 1513696980, 1513716480, 1527127381, 1527137761, 1527183721, 1527198121, 1527217501, 1527225841, 1527291841, 1527296161, 1527299041, 1527302701, 1527313021, 1527317041, 1527386521, 1527388801, 1527396061, 1527405121), class = c("POSIXct", "POSIXt"), tzone = "UTC")提取EMA每日首个触发时间:
从EMA数据中聚合得到每日最早的触发时间:data$Date_only <- as.Date(data$Time) data$Trigger_time <- as.POSIXct(data$Trigger_time, format = "%Y-%m-%d %H:%M:%S", tz = "UTC") first_trigger_times <- aggregate(Trigger_time ~ Date_only, data = data, FUN = min, na.rm = TRUE)输出结果如下:
> print(first_trigger_times) Date_only Trigger_time 1 2017-12-16 2017-12-16 06:52:11 2 2017-12-17 2017-12-17 06:38:45 3 2017-12-18 2017-12-18 05:37:12 4 2017-12-19 2017-12-19 07:13:43 5 2018-05-24 2018-05-24 05:33:56 6 2018-05-25 2018-05-25 06:27:33 7 2018-05-26 2018-05-26 06:44:41 8 2018-05-27 2018-05-27 07:13:45匹配最近唤醒时间的代码及问题:
使用sapply匹配每个触发时间对应的最近传感器唤醒时间:first_trigger_times$ClosestWakeUpTime <- sapply(first_trigger_times$Trigger_time, function(trigger_time) { closest_wake_up_time <- max(wake_up_times[wake_up_times <= trigger_time]) return(closest_wake_up_time) })结果中
ClosestWakeUpTime列显示为时间戳(如1513407000),而非预期的日期时间格式(如2017-12-16 06:50:00 UTC)。
错误原因
sapply默认会将返回的结果简化为最紧凑的向量类型。由于POSIXct本质是存储为数值型的时间戳(从1970-01-01 UTC开始的秒数),当sapply处理POSIXct对象时,会自动剥离其类属性,只保留底层的数值,导致最终列显示为时间戳而非日期时间格式。
解决方案
提供两种可行的修正方法:
方法1:使用lapply并转换为POSIXct向量
lapply不会自动简化结果,会返回列表,之后可以将列表转换为POSIXct向量并赋值给列:
first_trigger_times$ClosestWakeUpTime <- as.POSIXct( unlist(lapply(first_trigger_times$Trigger_time, function(trigger_time) { max(wake_up_times[wake_up_times <= trigger_time]) })), origin = "1970-01-01", tz = "UTC" )
方法2:使用dplyr的rowwise进行逐行处理(更优雅)
利用dplyr的逐行操作,保留POSIXct类属性:
library(dplyr) first_trigger_times <- first_trigger_times %>% rowwise() %>% mutate(ClosestWakeUpTime = max(wake_up_times[wake_up_times <= Trigger_time])) %>% ungroup()
方法3:在sapply中强制保留类属性
可以在函数返回时显式指定类,不过需要注意处理空值情况:
first_trigger_times$ClosestWakeUpTime <- sapply(first_trigger_times$Trigger_time, function(trigger_time) { closest_val <- max(wake_up_times[wake_up_times <= trigger_time]) structure(closest_val, class = c("POSIXct", "POSIXt"), tzone = "UTC") })
执行任意一种方法后,ClosestWakeUpTime列都会以预期的日期时间格式显示。
内容的提问来源于stack exchange,提问作者magg

