计算 R 中指定条件之前 30 秒的平均值
Calculate average of values 30 seconds prior to a specified condition in R
我有海豹的一系列潜水数据。我想计算潜水开始前 30 秒内海豹的心率。但是,我不确定如何告诉 R,如果遇到潜水开始,从该开始时间返回 30 秒并计算平均心率。我假设它需要是一个循环,条件是如果该行包含潜水开始,然后返回并在该开始前的最后 30 秒取平均值。
我真的希望这是可能的,我很难想象用我的数据计算这些信息的任何其他方法。
我的数据看起来像这样,潜水开始前有 NA 潜水信息,然后是潜水数据开始的潜水开始时间。数据帧中有多次潜水,在潜水之间可能有几分钟的时间它们悬挂在数据为 NA 的表面。但我只对计算潜水开始前 30 秒的心率感兴趣,而不是潜水之间的全部时间。注意:在用时间计算事物时,我倾向于使用纪元时间,因为这样更容易与 R 通信。
HR epoch datetime diveNum dive_start
1 103.44828 1523026041 2018-04-06 14:47:21 NA NA
2 82.19178 1523026041 2018-04-06 14:47:21 NA NA
3 88.23529 1523026042 2018-04-06 14:47:22 NA NA
4 95.23810 1523026043 2018-04-06 14:47:23 NA NA
5 90.90909 1523026043 2018-04-06 14:47:23 NA NA
6 88.23529 1523026044 2018-04-06 14:47:24 NA NA
7 84.50704 1523026045 2018-04-06 14:47:25 NA NA
8 84.50704 1523026045 2018-04-06 14:47:25 NA NA
9 82.19178 1523026046 2018-04-06 14:47:26 NA NA
10 80.00000 1523026047 2018-04-06 14:47:27 NA NA
11 80.00000 1523026047 2018-04-06 14:47:27 NA NA
12 81.08108 1523026048 2018-04-06 14:47:28 NA NA
13 80.00000 1523026049 2018-04-06 14:47:29 NA NA
14 78.94737 1523026050 2018-04-06 14:47:30 NA NA
15 68.18182 1523026050 2018-04-06 14:47:30 NA NA
16 60.00000 1523026051 2018-04-06 14:47:31 NA NA
17 40.26846 1523026052 2018-04-06 14:47:32 NA NA
18 49.18033 1523026054 2018-04-06 14:47:34 NA NA
19 48.00000 1523026055 2018-04-06 14:47:35 NA NA
20 48.38710 1523026056 2018-04-06 14:47:36 NA NA
21 48.00000 1523026058 2018-04-06 14:47:38 NA NA
22 49.18033 1523026059 2018-04-06 14:47:39 NA NA
23 50.84746 1523026060 2018-04-06 14:47:40 NA NA
24 52.17391 1523026061 2018-04-06 14:47:41 NA NA
25 44.44444 1523026062 2018-04-06 14:47:42 NA NA
26 47.61905 1523026064 2018-04-06 14:47:44 NA NA
27 44.77612 1523026065 2018-04-06 14:47:45 NA NA
28 43.79562 1523026066 2018-04-06 14:47:46 NA NA
29 34.88372 1523026068 2018-04-06 14:47:48 NA NA
30 36.58537 1523026069 2018-04-06 14:47:49 NA NA
31 39.73510 1523026071 2018-04-06 14:47:51 1 1523026071
所以我希望 R 在遇到潜水开始时间时对这些前 30 秒的心率数据 (HR) 进行平均。理想情况下,我会在潜水开始时间的行中创建一个新列,即潜水前心率。
我试过 运行 如下所示的循环,但我只得到 NaN 值。我实际上是从 another post 得到这个循环的,但在我的情况下它似乎不起作用。我试着告诉 R,当纪元时间等于或大于潜水开始前 30 秒的时间,或者小于或等于潜水开始时间时,计算这段时间的 HR 平均值。但是我的代码没有让 R 知道它需要及时返回来计算平均值。
#setting up the column
df$prediveHR<-NA
# for each row
for (r in 1:nrow(df)) {
# find all the rows within the acceptable timespan
# note: figure out if you want < vs <=
thisSubset = df[
df$epoch[r] >= df$predivetime[r] &
df$epoch[r] <= df$dive_start[r]
,]
# get the mean of the subset
df$prediveHR[r] = mean(thisSubset$HR)
}
我假设每一行是一秒钟。从你提供的数据看来是这样。
results <- c()
for (i in 1:nrow(df){
if (df$dive_start[i] != is.na(T){
results[i] <- mean(df$HR[(i-29):i]
}
}
如果第 dive_start 列不是 NA,我会询问每一行。如果它不是 NA,那么我们继续将 df$HR 的平均值写入结果向量。
我利用了这样一个事实,即在每次迭代中 i 等于当前行的数量。由于我们知道我们所在的行数,我们可以简单地减去 29 行作为我们的起始数字(在您的示例中 table 它将是 2),然后使用 i 作为 mean() 函数的结束行。
您可以通过这种方式轻松调整经期的长度。
这是一个基于{tidyverse}的解决方案。简而言之:
- 使用
tidyr::fill()
将潜水编号和开始时间传播回 pre-dive 周期,并使用它来计算潜水开始的秒数
- 在潜水开始后 30 秒内过滤到 pre-dive 行
- 计算每个
diveNum
内的平均 pre-dive HR
- 将计算的 pre-dive HR 合并回主数据帧
library(tidyverse)
pre_dive_data <- dive_data %>%
mutate(preDive = is.na(diveNum)) %>%
fill(diveNum, dive_start, .direction = "up") %>%
filter(preDive, dive_start - epoch <= 30) %>%
group_by(diveNum) %>%
summarize(preDiveHR = mean(HR))
dive_data <- dive_data %>%
left_join(pre_dive_data)
tail(dive_data)
输出:
# A tibble: 6 x 6
HR epoch datetime diveNum dive_start preDiveHR
<dbl> <dbl> <dttm> <dbl> <dbl> <dbl>
1 47.6 1523026064 2018-04-06 14:47:44 NA NA NA
2 44.8 1523026065 2018-04-06 14:47:45 NA NA NA
3 43.8 1523026066 2018-04-06 14:47:46 NA NA NA
4 34.9 1523026068 2018-04-06 14:47:48 NA NA NA
5 36.6 1523026069 2018-04-06 14:47:49 NA NA NA
6 39.7 1523026071 2018-04-06 14:47:51 1 1523026071 65.5
我有海豹的一系列潜水数据。我想计算潜水开始前 30 秒内海豹的心率。但是,我不确定如何告诉 R,如果遇到潜水开始,从该开始时间返回 30 秒并计算平均心率。我假设它需要是一个循环,条件是如果该行包含潜水开始,然后返回并在该开始前的最后 30 秒取平均值。
我真的希望这是可能的,我很难想象用我的数据计算这些信息的任何其他方法。
我的数据看起来像这样,潜水开始前有 NA 潜水信息,然后是潜水数据开始的潜水开始时间。数据帧中有多次潜水,在潜水之间可能有几分钟的时间它们悬挂在数据为 NA 的表面。但我只对计算潜水开始前 30 秒的心率感兴趣,而不是潜水之间的全部时间。注意:在用时间计算事物时,我倾向于使用纪元时间,因为这样更容易与 R 通信。
HR epoch datetime diveNum dive_start
1 103.44828 1523026041 2018-04-06 14:47:21 NA NA
2 82.19178 1523026041 2018-04-06 14:47:21 NA NA
3 88.23529 1523026042 2018-04-06 14:47:22 NA NA
4 95.23810 1523026043 2018-04-06 14:47:23 NA NA
5 90.90909 1523026043 2018-04-06 14:47:23 NA NA
6 88.23529 1523026044 2018-04-06 14:47:24 NA NA
7 84.50704 1523026045 2018-04-06 14:47:25 NA NA
8 84.50704 1523026045 2018-04-06 14:47:25 NA NA
9 82.19178 1523026046 2018-04-06 14:47:26 NA NA
10 80.00000 1523026047 2018-04-06 14:47:27 NA NA
11 80.00000 1523026047 2018-04-06 14:47:27 NA NA
12 81.08108 1523026048 2018-04-06 14:47:28 NA NA
13 80.00000 1523026049 2018-04-06 14:47:29 NA NA
14 78.94737 1523026050 2018-04-06 14:47:30 NA NA
15 68.18182 1523026050 2018-04-06 14:47:30 NA NA
16 60.00000 1523026051 2018-04-06 14:47:31 NA NA
17 40.26846 1523026052 2018-04-06 14:47:32 NA NA
18 49.18033 1523026054 2018-04-06 14:47:34 NA NA
19 48.00000 1523026055 2018-04-06 14:47:35 NA NA
20 48.38710 1523026056 2018-04-06 14:47:36 NA NA
21 48.00000 1523026058 2018-04-06 14:47:38 NA NA
22 49.18033 1523026059 2018-04-06 14:47:39 NA NA
23 50.84746 1523026060 2018-04-06 14:47:40 NA NA
24 52.17391 1523026061 2018-04-06 14:47:41 NA NA
25 44.44444 1523026062 2018-04-06 14:47:42 NA NA
26 47.61905 1523026064 2018-04-06 14:47:44 NA NA
27 44.77612 1523026065 2018-04-06 14:47:45 NA NA
28 43.79562 1523026066 2018-04-06 14:47:46 NA NA
29 34.88372 1523026068 2018-04-06 14:47:48 NA NA
30 36.58537 1523026069 2018-04-06 14:47:49 NA NA
31 39.73510 1523026071 2018-04-06 14:47:51 1 1523026071
所以我希望 R 在遇到潜水开始时间时对这些前 30 秒的心率数据 (HR) 进行平均。理想情况下,我会在潜水开始时间的行中创建一个新列,即潜水前心率。
我试过 运行 如下所示的循环,但我只得到 NaN 值。我实际上是从 another post 得到这个循环的,但在我的情况下它似乎不起作用。我试着告诉 R,当纪元时间等于或大于潜水开始前 30 秒的时间,或者小于或等于潜水开始时间时,计算这段时间的 HR 平均值。但是我的代码没有让 R 知道它需要及时返回来计算平均值。
#setting up the column
df$prediveHR<-NA
# for each row
for (r in 1:nrow(df)) {
# find all the rows within the acceptable timespan
# note: figure out if you want < vs <=
thisSubset = df[
df$epoch[r] >= df$predivetime[r] &
df$epoch[r] <= df$dive_start[r]
,]
# get the mean of the subset
df$prediveHR[r] = mean(thisSubset$HR)
}
我假设每一行是一秒钟。从你提供的数据看来是这样。
results <- c()
for (i in 1:nrow(df){
if (df$dive_start[i] != is.na(T){
results[i] <- mean(df$HR[(i-29):i]
}
}
如果第 dive_start 列不是 NA,我会询问每一行。如果它不是 NA,那么我们继续将 df$HR 的平均值写入结果向量。
我利用了这样一个事实,即在每次迭代中 i 等于当前行的数量。由于我们知道我们所在的行数,我们可以简单地减去 29 行作为我们的起始数字(在您的示例中 table 它将是 2),然后使用 i 作为 mean() 函数的结束行。
您可以通过这种方式轻松调整经期的长度。
这是一个基于{tidyverse}的解决方案。简而言之:
- 使用
tidyr::fill()
将潜水编号和开始时间传播回 pre-dive 周期,并使用它来计算潜水开始的秒数 - 在潜水开始后 30 秒内过滤到 pre-dive 行
- 计算每个
diveNum
内的平均 pre-dive HR
- 将计算的 pre-dive HR 合并回主数据帧
library(tidyverse)
pre_dive_data <- dive_data %>%
mutate(preDive = is.na(diveNum)) %>%
fill(diveNum, dive_start, .direction = "up") %>%
filter(preDive, dive_start - epoch <= 30) %>%
group_by(diveNum) %>%
summarize(preDiveHR = mean(HR))
dive_data <- dive_data %>%
left_join(pre_dive_data)
tail(dive_data)
输出:
# A tibble: 6 x 6
HR epoch datetime diveNum dive_start preDiveHR
<dbl> <dbl> <dttm> <dbl> <dbl> <dbl>
1 47.6 1523026064 2018-04-06 14:47:44 NA NA NA
2 44.8 1523026065 2018-04-06 14:47:45 NA NA NA
3 43.8 1523026066 2018-04-06 14:47:46 NA NA NA
4 34.9 1523026068 2018-04-06 14:47:48 NA NA NA
5 36.6 1523026069 2018-04-06 14:47:49 NA NA NA
6 39.7 1523026071 2018-04-06 14:47:51 1 1523026071 65.5