R编程:在给定特定ID的情况下,如何查找每两个连续日期的值差异
以下是我的数据集的简化版本:R编程:在给定特定ID的情况下,如何查找每两个连续日期的值差异,r,R,以下是我的数据集的简化版本: > df ID total_sleep sleep_end_date 1 1 9 2017-09-03 2 1 8 2017-09-04 3 1 7 2017-09-05 4 1 10 2017-09-06 5 1 11 2017-09-07 6 2 5 2017-0
> df
ID total_sleep sleep_end_date
1 1 9 2017-09-03
2 1 8 2017-09-04
3 1 7 2017-09-05
4 1 10 2017-09-06
5 1 11 2017-09-07
6 2 5 2017-09-03
7 2 12 2017-09-04
8 2 4 2017-09-05
9 2 3 2017-09-06
10 2 6 2017-09-07
其中总睡眠时间以小时表示
我试图找到的是,给定一个特定的用户ID,每两个连续日期的睡眠时间的绝对差异。所需的输出应该如下所示:
> df_answer
ID total_sleep sleep_end_date diff_hours_of_sleep
1 1 9 2017-09-03 NA
2 1 8 2017-09-04 1
3 1 7 2017-09-05 1
4 1 10 2017-09-06 3
5 1 11 2017-09-07 1
6 2 5 2017-09-03 NA
7 2 12 2017-09-04 7
8 2 4 2017-09-05 8
9 2 3 2017-09-06 1
10 2 6 2017-09-08 NA
NA出现在第1行和第6行,因为它没有关于前一天的任何数据
最重要的是,NA出现在第10行,因为我没有关于前一天(2017-09-07)的任何数据。这是我编写代码时最棘手的部分
我已经在谷歌上搜索过(意思是:“StackOverflow”),并试图使用dplyr的“数据争用备忘单”找到一个解决方案,但我还没有找到一个函数,使我能够在考虑到这两个变量的情况下做我想做的事情:日期和不同的用户ID
我是R的初学者,所以我可能确实错过了一些简单的东西。欢迎任何意见或建议 ##按ID排序data.frame,然后增加睡眠结束日期(如果尚未排序)
## Order data.frame by IDs, then by increasing sleep_end_dates (if not already sorted)
df <- df[order(df$ID, df$sleep_end_date),]
## Calculate difference in total_sleep with previous entry
df$diff_hours_of_sleep <- c(NA,abs(diff(df$total_sleep)))
## If previous ID is not equal, replace diff_hours_of_sleep with NA
ind <- c(NA, diff(df$ID))
df$diff_hours_of_sleep[ind != 0] <- NA
## And if previous day wasn't yesterday, replace diff_hours_of_sleep with NA
day_ind <- c(NA, diff(df$sleep_end_date))
df$diff_hours_of_sleep[day_ind != 1] <- NA
df也许下面的方法可以做到
df <- lapply(split(df, df$ID), function(x){
y <- ifelse(diff(x$sleep_end_date) == 1, abs(diff(x$total_sleep)), NA)
x$diff_hours_of_sleep <- c(NA, y)
x
})
df <- do.call(rbind, df)
df
df这里是一个使用data.table的解决方案-
dt1 <- data.table(df, key=c('id', 'sleep_end_date'))
merge(
dt1[,.(id, total_sleep, sleep_end_date, i=.I - 1)],
dt1[,.(id, total_sleep, i=.I)], by=c('id','i'), all.x=TRUE) [,.(id,sleep_end_date,\
total_sleep.x,delta=total_sleep.y-total_sleep.x)]
id sleep_end_date total_sleep.x delta
1: 1 2017-09-03 9 NA
2: 1 2017-09-04 8 1
3: 1 2017-09-05 7 1
4: 1 2017-09-06 10 -3
5: 1 2017-09-07 11 -1
6: 2 2017-09-03 5 NA
7: 2 2017-09-04 12 -7
8: 2 2017-09-05 4 8
9: 2 2017-09-06 3 1
10: 2 2017-09-07 6 -3
dt1谢谢!在你的回答中,我意识到我的问题中遗漏了另一个重要的一点:有时我没有前一天的数据,我想在这些情况下生成NA,就像我在问题中介绍的示例一样。只是添加了两行新的行,这样做很有效!非常感谢。编辑问题!