R编程:如果给定特定ID,如何找到每两个连续日期的值差异

时间:2017-09-02 15:52:00

标签: 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-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

其中total_sleep以小时表示。

在给定特定用户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)的任何数据。这对我来说是最棘手的部分。

我已经google了(意思是:“stackoverflowed”)这个并试图找到一个使用“数据争论备忘单”为dplyr的解决方案,但我还没有找到一个能让我做我做的事情的功能想要考虑这两个变量:日期和不同的用户ID。

我是R的初学者,所以我可能确实错过了一些简单的东西。任何意见或建议都会非常受欢迎!

3 个答案:

答案 0 :(得分:2)

## 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

答案 1 :(得分:1)

以下可能会这样做。

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

答案 2 :(得分:0)

以下是使用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

我不确定性能与纯数据框架方法相比如何,但它确实可以很好地扩展;将输入集扩展到20,000行,这在我的系统上花了不到一秒钟。