I need to find the trendline based on the local minimum and maximum points in my data set. Then plot a trendline defining those maximum/minimum picks and find both trendlines equations. I have tried to find the maximum points based on daily delta but it is not exactly defined the picks because the time interval (x-axis) is not equal between all picks. can someone help to find a better code in Python or R?

my_data

Here is the code I use

> import matplotlib.pyplot as plt from scipy.misc import
> electrocardiogram from scipy.signal import find_peaks x = df1['Oxygen
> Corrected For Saturation (%)'] peaks, _ = find_peaks(x, height=120)
> plt.plot(x) plt.plot(peaks, x[peaks], "x") plt.plot(np.zeros_like(x),
> "--", color="gray") plt.show()

on this sample of my data set

 Time Series:
Start = 0 
End = 21599 
Frequency = 1 
   [1] 109.0126 109.0126 109.1412 109.1412 108.7555 108.8841
   [7] 108.8841 108.6270 108.7555 108.8841 108.6270 109.0126
  [13] 108.8841 108.7555 108.6270 108.8841 109.0763 108.9475
  [19] 109.0763 109.2051 109.0763 108.6900 109.2051 109.0763
  [25] 109.4626 109.4626 108.9475 108.9475 109.0763 109.0763
  [31] 109.7845 109.3975 109.0105 109.3975 109.2685 109.3975
  [37] 109.5265 109.5265 109.2685 109.3975 109.1395 109.3975
  [43] 109.5265 109.5265 109.2685 109.1395 109.2685 109.6555
  [49] 109.2051 108.8187 109.2685 109.3975 109.1395 109.3975
  [55] 109.5265 109.2051 109.6555 109.6555 109.5914 109.9778
  [61] 110.1065 110.2353 110.7504 110.8792 110.8792 110.6217
  [67] 111.0080 111.5231 111.3943 111.7807 112.0382 112.0382
  [73] 111.9095 112.5534 111.9095 112.2265 111.8408 112.4836
  [79] 112.3550 112.4836 112.7407 112.6121 112.9978 112.9978
  [85] 112.9978 112.8692 113.1263 113.5120 112.9978 112.9978
  [91] 113.6405 113.5120 113.5120 113.5120 113.7691 113.5682
  [97] 113.4399 113.3116 113.6965 113.3116 113.6965 113.9532
 [103] 113.4399 113.9532 113.8249 114.4665 114.3382 114.2098
 [109] 114.0815 114.3382 114.2098 114.2098 113.9532 114.7231
 [115] 114.1359 114.3921 114.3921 114.3921 114.5202 114.3921
 [121] 114.5202 114.5202 114.6483 114.5202 114.5202 114.5202
 [127] 114.3921 114.3921 114.5202 114.7764 114.5202 114.6483
 [133] 114.3173 114.5730 114.4451 114.4451 114.5730 114.3173
 [139] 114.4451 114.1894 114.1894 114.0615 114.3173 114.0615
 [145] 113.9337 113.9867 113.0931 113.7314 113.8590 113.7314
 [151] 113.2208 113.4761 112.9655 113.0931 113.3484 113.0931
 [157] 113.0931 112.6371 112.6371 112.3823 112.7646 112.5097
 [163] 112.6371 112.5097 112.2549 112.7646 112.5097 111.6733
 [169] 111.5461 112.1820 112.3092 111.5461 111.9276 112.0548
 [175] 111.6733 111.4189 111.4189 111.8004 111.6008 111.2199
 [181] 111.4739 111.2199 110.8390 110.9660 111.2199 110.5851
 [187] 110.8390 110.9660 110.1338 110.3873 110.6408 110.6408
 [193] 110.5140 110.3873 110.5140 110.2606 110.1338 110.0071
 [199] 110.1338 110.0071 110.0629 109.8099 109.4304 109.5569
 [205] 109.6834 109.6834 109.5569 109.5569 109.4304 109.4304
 [211] 109.3602 109.3602 109.3602 108.8550 109.1076 109.3602
 [217] 109.2339 109.2339 109.1076 108.9813 109.0373 108.7852
 [223] 108.9113 108.9113 108.9113 109.1634 108.6592 108.7852
 [229] 108.7852 109.0373 108.5891 108.7150 108.4633 108.5891
 [235] 108.5891 108.4633 108.4633 108.4633 108.7150 108.8408
 [241] 108.6442 108.5186 108.2674 108.2674 108.3930 108.5186
 [247] 108.5186 107.8906 107.8906 108.0162 108.6442 107.8208
 [253] 107.9461 107.8208 108.4476 108.1969 108.4476 108.1969
 [259] 108.4476 108.1969 108.1969 107.6253 108.5013 108.1259
 [265] 108.1259 108.2510 108.3762 108.2510 108.5013 108.1259
 [271] 108.2510 108.1793 107.8045 108.0544 108.5541 107.5547
 [277] 107.9295 108.4291 107.9295 108.3042 107.9295 108.3042
 [283] 108.4812 108.3565 108.4812 107.8577 108.4812 107.7330
 [289] 108.2318 108.1071 108.1071 107.7330 107.8577 107.7855
 [295] 108.0344 107.9100 108.2834 107.5366 107.9100 108.1589
 [301] 108.4078 108.2834 107.9100 107.9100 107.8371 107.9613
 [307] 107.8371 107.9613 107.8371 107.8371 108.2098 108.2098
 [313] 108.0855 108.3340 108.3340 108.2098 108.0117 108.0117
 [319] 108.1357 108.0117 107.8877 108.3837 108.0117 108.1357
 [325] 108.0117 107.5156 108.0117 108.5077 108.0611 107.8136
 [331] 108.0611 107.5660 108.0611 108.0611 108.1849 108.0611
 [337] 108.0611 108.3087 108.3087 107.8136 108.2332 108.0611
 [343] 108.1097 108.3568 108.3568 108.4803 108.3568 108.1097
 [349] 108.1097 108.1097 108.4803 108.6039 108.3568 108.1573
 [355] 107.7873 108.1573 108.5272 108.4039 107.9106 107.9106
 [361] 108.1573 107.9106 107.7873 108.5272 108.5272 108.4039
 [367] 107.8346 108.2039 107.8346 107.8346 108.2039 107.7115
 [373] 107.9577 108.3270 108.2039 108.5732 108.3270 108.0808
 [379] 108.3270 108.0039 108.6183 108.1268 108.2497 108.0039
 [ reached getOption("max.print") -- omitted 20600 entries ]

enter code here

1

There are 1 best solutions below

2
On

I have created a sample time series

sr <- structure(c(0.5310173262842, 3.25572767108437, 6.00767408770848, 
                  8.71720569481067, 8.90061816157005, 11.3458017843761, 11.8780239290408, 
                  11.1096200471215, 10.2181658307111, 7.68106828447771, 6.08254778842631, 
                  3.77331493831468, 2.32460612635739, -0.811806523306027, -2.46962251406902, 
                  -5.18619137803562, -6.52238138877948, -7.23973075138485, -9.13814405994064, 
                  -8.38349420197295, -7.47206814043925, -7.72147447793804, -5.12452856469364, 
                  -4.04683892896908, -1.35807110614903, 1.40646738165309, 3.14711512330267, 
                  6.17118408869602, 9.08529877801627, 9.49523162785118, 10.6822759141775, 
                  11.1978729275889, 10.6255041996972, 9.03268924066647, 8.7816883510026, 
                  6.47370739211879, 4.40580528986734, 0.533166586756382, -0.755683435784947, 
                  -3.75971635798706, -5.0257974169312, -7.03157815870787, -7.88414266256784, 
                  -8.86247513623675, -8.78863836972667, -7.51760749016628, -7.71480223824999, 
                  -4.97461916047327, -2.25199707926287, 0.119538577227733, 2.22116378000857, 
                  5.43904351026787, 6.80527350499474, 8.2510591969805, 9.23767804783509, 
                  10.0470098504673, 10.6010911738849, 10.4872767135332, 9.64970869918311, 
                  7.48135037953984, 6.40801706579295, 2.79031207338565, 0.600852117538769, 
                  -2.15253622003924, -3.83503298159308, -6.61090815235403, -7.70316354129315, 
                  -8.10580024430761, -9.8302474480025, -7.96747302316148, -8.13638775878717, 
                  -5.66703638619944, -4.71304119623848, -2.45278459538985, 0.318463293581571, 
                  3.67690911529415, 6.02662806215273, 7.20785518381208, 9.70040091817327, 
                  11.2627145970869, 10.8077036141603, 11.3232437762389, 10.0235316788413, 
                  8.60832270906468, 7.69576415826105, 4.414689864356, 3.0022564046734, 
                  -0.707176590987069, -2.92922440533753, -5.38398987977956, -7.07823691334916, 
                  -8.84206898836627, -8.50344794508366, -8.23613496644785, -7.99119305955105, 
                  -6.90263664771967, -5.99024120758212, -4.04179919691163, -0.88973938626927, 
                  1.20986658055334), .Tsp = c(1, 100, 1), class = "ts")

The function to locate the local maxima and local minima, as suggested by

Answer

find_peaks <- function (x, m = 3){
  shape <- diff(sign(diff(x, na.pad = FALSE)))
  pks <- sapply(which(shape < 0), FUN = function(i){
    z <- i - m + 1
    z <- ifelse(z > 0, z, 1)
    w <- i + m + 1
    w <- ifelse(w < length(x), w, length(x))
    if(all(x[c(z : i, (i + 2) : w)] <= x[i + 1])) return(i + 1) else return(numeric(0))
  })

Using the function (just need to add - to the name of the data set to get minima)

pk <-  find_peaks(sr) #finding the points at which local maxima occurs
mn <- find_peaks(-sr) #finding the points at which local minima occurs

plot(sr) #Plotting the curve
abline(a = coef(lm(sr[pk] ~ pk))[1], b = coef(lm(sr[pk] ~ pk))[2], col = 'green') #Trendline for local maxima
abline(a = coef(lm(sr[mn] ~ mn))[1], b=coef(lm(sr[mn]~mn))[2], col='red') #Trendline for local minima

The plot looks like this: enter image description here

I hope you could work around this with your data.