Good afternoon,
I have a vector of data (force
) in which values increase from low values, to a peak value, and then to low values again (repeating this trend twice), then creating two "waves" of data.
This is the code, in which I plot the force vector as a function of time
(for a better representation)
force <- c(0,0,0,0,3,4,5,3,0,6,8,9,10,14,21,25,12,10,8,5,0,4,3,4,6,0,3,15,20,24,50,80,150,180,200,250,332,369,470,578,690,540,444,378,299,254,200,130,79,55,29,17,4,5,2,7,8,3,5,7,6,1,2,9,11,20,23,15,4,5,6,8,18,20,29,40,55,69,100,144,189,245,300,415,555,696,500,434,321,279,249,150,130,68,50,43,23,19,4,5,4,5,3,2,0,5,3,4)
time <- seq(from=0, to=length(force)-1, by=1)
plot(time,force, type = "l", lty = 1)
What I would like to do is to cut the vector so as it only contains the two "waves" of data. A "wave" is defined when:
- First, data goes above 20
- Then, a threshold of 300 is crossed
- Finally, data goes below 20 again
So according to these criteria, a wave would be found every time the data goes above 20, crosses a certain threshold, in this case 300 and afterwards goes below 20.
Done manually, the force.cut
vector would be the desired result:
force.cut <- c(force[29:52],force[74:97])
time.cut <- seq(from=0, to=length(force.cut)-1, by=1)
plot(time.cut,force.cut, type = "l", lty = 1)
I am almost sure that the findpeaks
function from the pracma
package should be part of the solution, but I have not found the way to do exactly what I need. I am sure that there should be an easy way to do it, though.
Thank you very much in advance for any help!
CodePudding user response:
A quick try:
force <- c(0,0,0,0,3,4,5,3,0,6,8,9,10,14,21,25,12,10,8,5,0,4,3,4,6,0,3,15,20,24,50,80,150,180,200,250,332,369,470,578,690,540,444,378,299,254,200,130,79,55,29,17,4,5,2,7,8,3,5,7,6,1,2,9,11,20,23,15,4,5,6,8,18,20,29,40,55,69,100,144,189,245,300,415,555,696,500,434,321,279,249,150,130,68,50,43,23,19,4,5,4,5,3,2,0,5,3,4)
time <- seq(from=0, to=length(force)-1, by=1)
plot(time,force, type = "l", lty = 1)
a <- pracma::findpeaks(force, minpeakheight = 301, threshold = 20)
a
#> [,1] [,2] [,3] [,4]
#> [1,] 690 41 26 53
#> [2,] 696 86 69 99
plot(time, force, xlim =c(a[1,3], a[1,4]), type = "l")
Created on 2022-10-15 with reprex v2.0.2
Regards, Grzegorz
CodePudding user response:
Here's an option using a for loop...
library(pracma)
peaks <- findpeaks(force, threshold = 20, minpeakheight = 300)
peak_period <- colSums(peaks)[4] - colSums(peaks)[3] nrow(peaks)
peak_vec <- vector(mode = "numeric", length = peak_period)
w_start <- 1
for(i in seq_len(nrow(peaks))){
len_i <- length(peaks[i, 3] : peaks[i, 4])
w_end <- w_start len_i-1
peak_vec[w_start:w_end] <- c(peaks[i, 3]:peaks[i, 4])
w_start <- len_i w_start
}
plot(1:peak_period, force[peak_vec], type = "l", lty = 1, ylab = "Force", xlab = "Time")
Created on 2022-10-15 with reprex v2.0.2