此数据与使用不同时间戳进行两项活动的人员有关。让我详细解释数据。
我有两张桌子,一张是人们去锻炼的时间,另一张是他们的血压和次数(频率)。
表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.你能告诉我,有没有更有效的方法呢?
答案 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类。