如何在一个时间 window 中找到多个变量的同步增加?
How to find synchronous increases of multiple variables in a time window?
我有一个非常大的数据框,其中包含在连续时间内对不同对象进行的测量。我需要过滤掉那些 在特定时间 window.
所有受试者同步增加的测量值
这是一些模拟数据; v1
和 v2
是对两个对象进行的测量:
df <- data.frame(
time = 1:30,
v1 = c(4,4,4,4,4, 2,4,5,5,6,
6,6,6,6,6, 5,5,6,7,7,
7,6,5,6,4, 5,5,5,5,4),
v2 = c(0.93,0.82,0.99,1.01,1.01, 1.01,1.01,1.56,1.80,1.99,
1.01,0.05,1.05,1.02,0.01, 1.11,1.11,1.40,1.42,1.45,
1.00,1.00,1.11,1.99,1.34, 2.45,3.00,3.67,3.67,3.88)
)
让我们假设时间 window 为 5 秒。我如何检测 df
中的那些行,在 5 秒内 window,v1
和 v2
中的值同步增加?通过“增加”我的意思是:
5 值序列中的任何值都不得小于序列第一个值,并且至少序列最后一个值必须大于序列第一个值。也就是说,1,1,1,1,2
算作增加,而 1,0,1,2,3
则不算。我还想通过一些分组标签对每个同步增加进行分组,例如 a
、b
等。所需的输出将是:
df1
time v1 v2 group
6 6 2 1.01 a
7 7 4 1.01 a
8 8 5 1.56 a
9 9 5 1.80 a
10 10 6 1.99 a
16 16 5 1.11 b
17 17 5 1.11 b
18 18 6 1.40 b
19 19 7 1.42 b
20 20 7 1.45 b
25 25 4 1.34 c
26 26 5 2.45 c
27 27 5 3.00 c
28 28 5 3.67 c
29 29 5 3.67 c
如何做到这一点?非常感谢帮助。
你可以试试这个方法:
保持它的灵活性以适应任意数量的测量(第 v1
、v2
...vn
列)。
library(dplyr)
library(data.table)
window_size <- 5
result1 <- df %>%
mutate(across(c(v1, v2), ~lead(.) - ., .names = '{col}_diff')) %>%
mutate(result = {tmp <- select(., ends_with('diff'));
rowSums(tmp >= 0) == length(tmp)},
group = rleid(result)) %>%
group_by(group) %>%
filter(n() >= window_size - 1)
result1
# A tibble: 12 x 7
# Groups: group [3]
# time v1 v2 v1_diff v2_diff result group
# <int> <dbl> <dbl> <dbl> <dbl> <lgl> <int>
# 1 6 2 1.01 2 0 TRUE 4
# 2 7 4 1.01 1 0.55 TRUE 4
# 3 8 5 1.56 0 0.24 TRUE 4
# 4 9 5 1.8 1 0.190 TRUE 4
# 5 16 5 1.11 0 0 TRUE 8
# 6 17 5 1.11 1 0.290 TRUE 8
# 7 18 6 1.4 1 0.02 TRUE 8
# 8 19 7 1.42 0 0.03 TRUE 8
# 9 25 4 1.34 1 1.11 TRUE 12
#10 26 5 2.45 0 0.550 TRUE 12
#11 27 5 3 0 0.67 TRUE 12
#12 28 5 3.67 0 0 TRUE 12
请注意,我们在 filter
中有 window_size - 1
,这是必需的,因为我们用 lead
行减去当前行,这对于每组中的最后一行来说是负数.这也是最后一行不包含在同一组中的原因。如果时间是连续的,您可以从每个组中获得下一个值为 time
的行。
result2 <- df %>%
filter(time %in% (result1 %>% slice(n()) %>% pull(time) + 1))
result2
# time v1 v2
#1 10 6 1.99
#2 20 7 1.45
#3 29 5 3.67
现在 rbind
result1
和 result2
仅保留 result1
.
中的相关列
以下方法将每隔 n 行将数据分成不同的组。因此,如果您想检查 0-5、6-10、11-16 的条件,...这将起作用
library(dplyr)
#storing the window size
n1 <- 5L
#code for result
df %>% group_by(dummy = (row_number()-1) %/% n1) %>%
filter((last(v1) > first(v1) &
v1 >= first(v1) &
last(v2) > first(v2) &
v2 >= first(v2))) %>%
ungroup() %>%
mutate(grp = letters[dense_rank(dummy)])
# A tibble: 10 x 5
time v1 v2 dummy grp
<int> <dbl> <dbl> <dbl> <chr>
1 6 2 1.01 1 a
2 7 4 1.01 1 a
3 8 5 1.56 1 a
4 9 5 1.8 1 a
5 10 6 1.99 1 a
6 16 5 1.11 3 b
7 17 5 1.11 3 b
8 18 6 1.4 3 b
9 19 7 1.42 3 b
10 20 7 1.45 3 b
我有一个非常大的数据框,其中包含在连续时间内对不同对象进行的测量。我需要过滤掉那些 在特定时间 window.
所有受试者同步增加的测量值这是一些模拟数据; v1
和 v2
是对两个对象进行的测量:
df <- data.frame(
time = 1:30,
v1 = c(4,4,4,4,4, 2,4,5,5,6,
6,6,6,6,6, 5,5,6,7,7,
7,6,5,6,4, 5,5,5,5,4),
v2 = c(0.93,0.82,0.99,1.01,1.01, 1.01,1.01,1.56,1.80,1.99,
1.01,0.05,1.05,1.02,0.01, 1.11,1.11,1.40,1.42,1.45,
1.00,1.00,1.11,1.99,1.34, 2.45,3.00,3.67,3.67,3.88)
)
让我们假设时间 window 为 5 秒。我如何检测 df
中的那些行,在 5 秒内 window,v1
和 v2
中的值同步增加?通过“增加”我的意思是:
5 值序列中的任何值都不得小于序列第一个值,并且至少序列最后一个值必须大于序列第一个值。也就是说,1,1,1,1,2
算作增加,而 1,0,1,2,3
则不算。我还想通过一些分组标签对每个同步增加进行分组,例如 a
、b
等。所需的输出将是:
df1
time v1 v2 group
6 6 2 1.01 a
7 7 4 1.01 a
8 8 5 1.56 a
9 9 5 1.80 a
10 10 6 1.99 a
16 16 5 1.11 b
17 17 5 1.11 b
18 18 6 1.40 b
19 19 7 1.42 b
20 20 7 1.45 b
25 25 4 1.34 c
26 26 5 2.45 c
27 27 5 3.00 c
28 28 5 3.67 c
29 29 5 3.67 c
如何做到这一点?非常感谢帮助。
你可以试试这个方法:
保持它的灵活性以适应任意数量的测量(第 v1
、v2
...vn
列)。
library(dplyr)
library(data.table)
window_size <- 5
result1 <- df %>%
mutate(across(c(v1, v2), ~lead(.) - ., .names = '{col}_diff')) %>%
mutate(result = {tmp <- select(., ends_with('diff'));
rowSums(tmp >= 0) == length(tmp)},
group = rleid(result)) %>%
group_by(group) %>%
filter(n() >= window_size - 1)
result1
# A tibble: 12 x 7
# Groups: group [3]
# time v1 v2 v1_diff v2_diff result group
# <int> <dbl> <dbl> <dbl> <dbl> <lgl> <int>
# 1 6 2 1.01 2 0 TRUE 4
# 2 7 4 1.01 1 0.55 TRUE 4
# 3 8 5 1.56 0 0.24 TRUE 4
# 4 9 5 1.8 1 0.190 TRUE 4
# 5 16 5 1.11 0 0 TRUE 8
# 6 17 5 1.11 1 0.290 TRUE 8
# 7 18 6 1.4 1 0.02 TRUE 8
# 8 19 7 1.42 0 0.03 TRUE 8
# 9 25 4 1.34 1 1.11 TRUE 12
#10 26 5 2.45 0 0.550 TRUE 12
#11 27 5 3 0 0.67 TRUE 12
#12 28 5 3.67 0 0 TRUE 12
请注意,我们在 filter
中有 window_size - 1
,这是必需的,因为我们用 lead
行减去当前行,这对于每组中的最后一行来说是负数.这也是最后一行不包含在同一组中的原因。如果时间是连续的,您可以从每个组中获得下一个值为 time
的行。
result2 <- df %>%
filter(time %in% (result1 %>% slice(n()) %>% pull(time) + 1))
result2
# time v1 v2
#1 10 6 1.99
#2 20 7 1.45
#3 29 5 3.67
现在 rbind
result1
和 result2
仅保留 result1
.
以下方法将每隔 n 行将数据分成不同的组。因此,如果您想检查 0-5、6-10、11-16 的条件,...这将起作用
library(dplyr)
#storing the window size
n1 <- 5L
#code for result
df %>% group_by(dummy = (row_number()-1) %/% n1) %>%
filter((last(v1) > first(v1) &
v1 >= first(v1) &
last(v2) > first(v2) &
v2 >= first(v2))) %>%
ungroup() %>%
mutate(grp = letters[dense_rank(dummy)])
# A tibble: 10 x 5
time v1 v2 dummy grp
<int> <dbl> <dbl> <dbl> <chr>
1 6 2 1.01 1 a
2 7 4 1.01 1 a
3 8 5 1.56 1 a
4 9 5 1.8 1 a
5 10 6 1.99 1 a
6 16 5 1.11 3 b
7 17 5 1.11 3 b
8 18 6 1.4 3 b
9 19 7 1.42 3 b
10 20 7 1.45 3 b