我已经创建了我的数据的简化版本:
a <- data.frame(a = c(0,1,2,3,2,1,0,-1,-2,-3,-2,-1,
0,1,2,3,4,3,2,1,0,-1,-2,-3,-2,-1,
0,1,2,1,0,-1,-2,-3,-2,-1,0,1,2,3,2,1,
0,-1,-2,-3,-2,-1,0,1,2,3,2,1,
0,-1,-2,-3,-4,-3,-2,-1,0))
a$b <- seq(1,length(a$a),1)
我尝试检测数据中的周期如下(对更好的建议开放):library(quantmod)
max <- findPeaks(a$a)
min <- findValleys(a$a)
这实际上给出了最大值和最小值之后的点。我想找到每个周期的跨度和设定点。周期: - 第一个周期定义为第一个数据点到第一个设定点之前的数据点。例如,考虑到第一个设定点是 -1.0,第一个循环定义在第 1 行到第 12 行。第 12 行被选为循环结束,因为它出现在第一个峰值和谷值之后,并且也等于或小于 - 1.0.第二个循环从第 13 行开始到第 27 行,因为第 27 行的振幅为 0,小于或等于 0.5,并且发生在第二个峰值和谷值点之后:
span <- a[max-1,]$a-a[min-1,]$a
set <- a[max,]$a - span/2
我想对原始数据框中的数据进行分组 a
并将每个循环(组)的循环编号、跨度和设定点分配给相应的行组。所需的输出是:
> print(a)
a b cycles span set
1 0 1 1 6 -1.0
2 1 2 1 6 -1.0
3 2 3 1 6 -1.0
4 3 4 1 6 -1.0
5 2 5 1 6 -1.0
6 1 6 1 6 -1.0
7 0 7 1 6 -1.0
8 -1 8 1 6 -1.0
9 -2 9 1 6 -1.0
10 -3 10 1 6 -1.0
11 -2 11 1 6 -1.0
12 -1 12 1 6 -1.0
13 0 13 2 7 0.5
14 1 14 2 7 0.5
15 2 15 2 7 0.5
16 3 16 2 7 0.5
17 4 17 2 7 0.5
18 3 18 2 7 0.5
19 2 19 2 7 0.5
20 1 20 2 7 0.5
21 0 21 2 7 0.5
22 -1 22 2 7 0.5
23 -2 23 2 7 0.5
24 -3 24 2 7 0.5
25 -2 25 2 7 0.5
26 -1 26 2 7 0.5
27 0 27 2 7 0.5
28 1 28 3 5 -1.5
29 2 29 3 5 -1.5
30 1 30 3 5 -1.5
31 0 31 3 5 -1.5
32 -1 32 3 5 -1.5
33 -2 33 3 5 -1.5
34 -3 34 3 5 -1.5
35 -2 35 3 5 -1.5
36 -1 36 4 6 -1.0
37 0 37 4 6 -1.0
38 1 38 4 6 -1.0
39 2 39 4 6 -1.0
40 3 40 4 6 -1.0
41 2 41 4 6 -1.0
42 1 42 4 6 -1.0
43 0 43 4 6 -1.0
44 -1 44 4 6 -1.0
45 -2 45 4 6 -1.0
46 -3 46 4 6 -1.0
47 -2 47 4 6 -1.0
48 -1 48 4 6 -1.0
49 0 49 5 7 -1.5
50 1 50 5 7 -1.5
51 2 51 5 7 -1.5
52 3 52 5 7 -1.5
53 2 53 5 7 -1.5
54 1 54 5 7 -1.5
55 0 55 5 7 -1.5
56 -1 56 5 7 -1.5
57 -2 57 5 7 -1.5
58 -3 58 5 7 -1.5
59 -4 59 5 7 -1.5
60 -3 60 5 7 -1.5
61 -2 61 5 7 -1.5
62 -1 62 5 7 -1.5
63 0 63 5 7 -1.5
最佳答案
鉴于循环的定义,我认为您的循环应该在第 12、27、36、48 和 62 行结束,因此总共是 6 个循环而不是 5 个。实际上只有 5 个完整的循环。
为了简单和区分,一些数据/对象的名称已更改-
给定的对象
df_a <- data.frame(a = c(0,1,2,3,2,1,0,-1,-2,-3,-2,-1,
0,1,2,3,4,3,2,1,0,-1,-2,-3,-2,-1,
0,1,2,1,0,-1,-2,-3,-2,-1,0,1,2,3,2,1,
0,-1,-2,-3,-2,-1,0,1,2,3,2,1,
0,-1,-2,-3,-4,-3,-2,-1,0))
df_a$b <- seq(1,length(df_a$a),1)
df_a
my_max <- findPeaks(df_a$a)
my_min <- findValleys(df_a$a)
span <- df_a[my_max-1,]$a-df_a[my_min-1,]$a
set <- df_a[my_max,]$a - span/2
建议用于循环的代码# generate a for loop to calculate end of cycle
my_vec <- NULL # create a null vector
#create a my_vec through for loop
for(i in seq_along(my_max)){
my_vec[i] <- which(df_a$b > max(my_max[i], my_min[i]) & df_a$a >= set[i])[1]
}
library(tidyverse) # for cumsum function
#create cycle column
df_a$cycle <- rev(cumsum(rev(df_a$b %in% my_vec)))
#check
> df_a
a b cycle
1 0 1 5
2 1 2 5
3 2 3 5
4 3 4 5
5 2 5 5
6 1 6 5
7 0 7 5
8 -1 8 5
9 -2 9 5
10 -3 10 5
11 -2 11 5
12 -1 12 5
13 0 13 4
14 1 14 4
15 2 15 4
16 3 16 4
17 4 17 4
18 3 18 4
19 2 19 4
20 1 20 4
21 0 21 4
22 -1 22 4
23 -2 23 4
24 -3 24 4
25 -2 25 4
26 -1 26 4
27 0 27 4
28 1 28 3
29 2 29 3
30 1 30 3
31 0 31 3
32 -1 32 3
33 -2 33 3
34 -3 34 3
35 -2 35 3
36 -1 36 3
37 0 37 2
38 1 38 2
39 2 39 2
40 3 40 2
41 2 41 2
42 1 42 2
43 0 43 2
44 -1 44 2
45 -2 45 2
46 -3 46 2
47 -2 47 2
48 -1 48 2
49 0 49 1
50 1 50 1
51 2 51 1
52 3 52 1
53 2 53 1
54 1 54 1
55 0 55 1
56 -1 56 1
57 -2 57 1
58 -3 58 1
59 -4 59 1
60 -3 60 1
61 -2 61 1
62 -1 62 1
63 0 63 0
上面的代码将反向生成循环数。但是,如果您需要按顺序使用它们,请执行此操作df_a$cycle <- max(rev(cumsum(rev(df_a$b %in% my_vec))))+1-rev(cumsum(rev(df_a$b %in% my_vec)))
df_a
> df_a
a b cycle
1 0 1 1
2 1 2 1
3 2 3 1
4 3 4 1
5 2 5 1
6 1 6 1
7 0 7 1
8 -1 8 1
9 -2 9 1
10 -3 10 1
11 -2 11 1
12 -1 12 1
13 0 13 2
14 1 14 2
15 2 15 2
16 3 16 2
17 4 17 2
18 3 18 2
19 2 19 2
20 1 20 2
21 0 21 2
22 -1 22 2
23 -2 23 2
24 -3 24 2
25 -2 25 2
26 -1 26 2
27 0 27 2
28 1 28 3
29 2 29 3
30 1 30 3
31 0 31 3
32 -1 32 3
33 -2 33 3
34 -3 34 3
35 -2 35 3
36 -1 36 3
37 0 37 4
38 1 38 4
39 2 39 4
40 3 40 4
41 2 41 4
42 1 42 4
43 0 43 4
44 -1 44 4
45 -2 45 4
46 -3 46 4
47 -2 47 4
48 -1 48 4
49 0 49 5
50 1 50 5
51 2 51 5
52 3 52 5
53 2 53 5
54 1 54 5
55 0 55 5
56 -1 56 5
57 -2 57 5
58 -3 58 5
59 -4 59 5
60 -3 60 5
61 -2 61 5
62 -1 62 5
63 0 63 6
旧代码my_vec <- NULL
for(i in seq_along(my_max)){
my_vec[1] <- 0
my_vec[i+1] <- which(df_a$b > max(my_max[i], my_min[i]) & df_a$a >= set[i])[1]
}
# generate column cycle as intended
df_a$cycle <- c(rep(1:length(my_max), diff(my_vec)), rep(length(my_max)+1, length(df_a$a)-length(rep(1:length(my_max), diff(my_vec)))))
a b cycle
1 0 1 1
2 1 2 1
3 2 3 1
4 3 4 1
5 2 5 1
6 1 6 1
7 0 7 1
8 -1 8 1
9 -2 9 1
10 -3 10 1
11 -2 11 1
12 -1 12 1
13 0 13 2
14 1 14 2
15 2 15 2
16 3 16 2
17 4 17 2
18 3 18 2
19 2 19 2
20 1 20 2
21 0 21 2
22 -1 22 2
23 -2 23 2
24 -3 24 2
25 -2 25 2
26 -1 26 2
27 0 27 2
28 1 28 3
29 2 29 3
30 1 30 3
31 0 31 3
32 -1 32 3
33 -2 33 3
34 -3 34 3
35 -2 35 3
36 -1 36 3
37 0 37 4
38 1 38 4
39 2 39 4
40 3 40 4
41 2 41 4
42 1 42 4
43 0 43 4
44 -1 44 4
45 -2 45 4
46 -3 46 4
47 -2 47 4
48 -1 48 4
49 0 49 5
50 1 50 5
51 2 51 5
52 3 52 5
53 2 53 5
54 1 54 5
55 0 55 5
56 -1 56 5
57 -2 57 5
58 -3 58 5
59 -4 59 5
60 -3 60 5
61 -2 61 5
62 -1 62 5
63 0 63 6
逻辑解释0
my_vec
将有每个周期的终点此后您可以加入已生成的列。
完整输出
df_b <- data.frame(cycle = 1:length(my_max))
df_b$span <- df_a[my_max-1,]$a-df_a[my_min-1,]$a
df_b$set <- df_a[my_max,]$a - span/2
merge(df_a, df_b, by.x = "cycle", by.y = "cycle", all = T)
cycle a b span set
1 1 0 1 6 -1.0
2 1 1 2 6 -1.0
3 1 3 4 6 -1.0
4 1 2 5 6 -1.0
5 1 1 6 6 -1.0
6 1 2 3 6 -1.0
7 1 -1 8 6 -1.0
8 1 -2 9 6 -1.0
9 1 -3 10 6 -1.0
10 1 0 7 6 -1.0
11 1 -1 12 6 -1.0
12 1 -2 11 6 -1.0
13 2 0 13 7 -0.5
14 2 1 14 7 -0.5
15 2 2 15 7 -0.5
16 2 4 17 7 -0.5
17 2 3 18 7 -0.5
18 2 2 19 7 -0.5
19 2 3 16 7 -0.5
20 2 0 21 7 -0.5
21 2 -1 22 7 -0.5
22 2 -2 23 7 -0.5
23 2 1 20 7 -0.5
24 2 -2 25 7 -0.5
25 2 -1 26 7 -0.5
26 2 0 27 7 -0.5
27 2 -3 24 7 -0.5
28 3 1 28 5 -1.5
29 3 1 30 5 -1.5
30 3 0 31 5 -1.5
31 3 -1 32 5 -1.5
32 3 2 29 5 -1.5
33 3 -3 34 5 -1.5
34 3 -2 35 5 -1.5
35 3 -1 36 5 -1.5
36 3 -2 33 5 -1.5
37 4 1 38 6 -1.0
38 4 2 39 6 -1.0
39 4 3 40 6 -1.0
40 4 2 41 6 -1.0
41 4 1 42 6 -1.0
42 4 0 43 6 -1.0
43 4 -1 44 6 -1.0
44 4 -2 45 6 -1.0
45 4 -3 46 6 -1.0
46 4 -2 47 6 -1.0
47 4 -1 48 6 -1.0
48 4 0 37 6 -1.0
49 5 0 49 7 -1.5
50 5 2 51 7 -1.5
51 5 3 52 7 -1.5
52 5 2 53 7 -1.5
53 5 1 54 7 -1.5
54 5 0 55 7 -1.5
55 5 -1 56 7 -1.5
56 5 -2 57 7 -1.5
57 5 -3 58 7 -1.5
58 5 -4 59 7 -1.5
59 5 -3 60 7 -1.5
60 5 -2 61 7 -1.5
61 5 -1 62 7 -1.5
62 5 1 50 7 -1.5
63 6 0 63 NA NA
我们可以检查一下library(tidyverse)
df_a %>% ggplot() +
geom_line(aes(x=b, y=a, linetype = as.character(cycle)))
关于r - 按周期对数据帧中的数据进行分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65801769/