使用时间戳

时间:2017-06-12 12:03:58

标签: r dataframe merge

此数据与使用不同时间戳进行两项活动的人员有关。让我详细解释数据。

我有两张桌子,一张是人们去锻炼的时间,另一张是他们的血压和次数(频率)。

表1:第一列是人的id,第二列是日期&锻炼的时间。

id  date_time
1   29-Oct-2016 6:01:03 PM
1   29-Oct-2016 7:34:17 PM
1   30-Oct-2016 2:08:03 PM
1   30-Oct-2016 3:55:12 PM
2   31-Oct-2016 11:32:12 AM
2   31-Oct-2016 2:59:56 PM
2   01-Nov-2016 12:49:44 PM
2   01-Nov-2016 1:55:16 PM
2   01-Nov-2016 7:18:22 PM
2   01-Nov-2016 8:40:48 PM
3   01-Nov-2016 9:19:50 PM
3   02-Nov-2016 2:20:15 PM
3   02-Nov-2016 6:52:27 PM
3   02-Nov-2016 7:39:32 PM
3   03-Nov-2016 8:55:41 AM

表2:它包括id和日期&所施用的血压测试的时间信息。最后一列是迄今为止所进行的测试的累积频率。

id  date_time   Cumulative_frequency
1   30-Oct-2016 2:07:03 PM  2
1   30-Oct-2016 3:56:12 PM  3
2   31-Oct-2016 11:31:12 AM 5
2   31-Oct-2016 3:00:56 PM  7
3   02-Nov-2016 7:40:32 PM  0
3   03-Nov-2016 8:54:41 AM  5

我必须将表2中的cumulative_frequency数据添加到表1.需要的是,对于每个id,需要知道在运动之前已经采取了多少次血压。下表是必需的结果。

表3:

   id   date_time               Cumulative_frequency
    1   29-Oct-2016 6:01:03 PM  0
    1   29-Oct-2016 7:34:17 PM  0
    1   30-Oct-2016 2:08:03 PM  2
    1   30-Oct-2016 3:55:12 PM  2
    2   31-Oct-2016 11:32:12 AM 5
    2   31-Oct-2016 2:59:56 PM  5
    2   01-Nov-2016 12:49:44 PM 7
    2   01-Nov-2016 1:55:16 PM  7
    2   01-Nov-2016 7:18:22 PM  7
    2   01-Nov-2016 8:40:48 PM  7
    3   01-Nov-2016 9:19:50 PM  0
    3   02-Nov-2016 2:20:15 PM  0
    3   02-Nov-2016 6:52:27 PM  0
    3   02-Nov-2016 7:39:32 PM  0
    3   03-Nov-2016 8:55:41 AM  5

我正在尝试执行以下操作:首先我对df wrt日期进行了排序。然后我使用for循环为每个id为每个数据集创建两个子集。然后,对于每个子集,我使用which比较日期。这是针对数据集1中的每个date_time,其中date_time较低,然后是最大索引。使用索引然后我获取频率。然后我使用merge来获取表3.你能告诉我,有没有更有效的方法呢?

2 个答案:

答案 0 :(得分:3)

data.table - 包的滚动连接功能与cummax - 功能相结合可能是解决此问题的好方法:

# convert the 'date_time' variables to date-time class
df1$date_time <- as.POSIXct(df1$date_time, '%d-%b-%Y %I:%M:%S %p', tz = 'GMT')
df2$date_time <- as.POSIXct(df2$date_time, '%d-%b-%Y %I:%M:%S %p', tz = 'GMT')

# load the 'data.table'-package and convert the data.frame-s to data.table-s
library(data.table)
setDT(df1)
setDT(df2)

# several steps to get the desired result:
# rolling join (line 1)
# replace missing frequency values with zero (line 2)
# get the cummulative max by 'id' (line 3)
df1[df2, on = .(id, date_time), roll = -Inf, c_freq := Cumulative_frequency
    ][is.na(c_freq), freq := 0
      ][, c_freq := cummax(c_freq), id][]

这给出了:

    id           date_time freq
 1:  1 2016-10-29 18:01:03    0
 2:  1 2016-10-29 19:34:17    0
 3:  1 2016-10-30 14:08:03    2
 4:  1 2016-10-30 15:55:12    2
 5:  2 2016-10-31 11:32:12    5
 6:  2 2016-10-31 14:59:56    5
 7:  2 2016-11-01 12:49:44    7
 8:  2 2016-11-01 13:55:16    7
 9:  2 2016-11-01 19:18:22    7
10:  2 2016-11-01 20:40:48    7
11:  3 2016-11-01 21:19:50    0
12:  3 2016-11-02 14:20:15    0
13:  3 2016-11-02 18:52:27    0
14:  3 2016-11-02 19:39:32    0
15:  3 2016-11-03 08:55:41    5

不需要cummax的替代方案(感谢@DavidArenburg):

df1[, c_freq := df2[df1, Cumulative_frequency, on = .(id, date_time), roll = Inf]
    ][is.na(c_freq), cum_freq := 0][]

答案 1 :(得分:1)

您可以先按ID将第二个数据框拆分为一个列表。对于每个练习,首先在列表中为正确的id进行子集,然后使用findInterval,在练习数据框中获得与日期最接近的匹配:

group_by, summarise and mutate commands

使用拆分列表,每次整个数据帧都不是子集,并且使用findInterval,不需要再次为整个数据帧进行子集化。

cumuls函数返回相同的频率。只需将它们与数据框绑定即可。

为什么我使用sapply而不是应用第一个边距:因为apply返回带有强制值的字符向量的向量,而子集行返回1行数据框,其中为第二个项保留POSIXct类。