Find the mean of the maxima for each curve in a series

Viewed 38

I have many (~10.000) values in one column. The values make a graph that contains many curves (between 35 and 40 curves), as shown in the example below. Each curve is separated from each other by a series of zeroes.

enter image description here

Is it possible for R to recognize the maximal values of each curve? In other words, can it recognize the maximal values between the “zero-values”? I do not need the separate maxima (peak) of each curve – I need the need the mean values of all maximal values.

I have tried it with origin and excel – it works but many clicks are needed and I have to repeat the procedure for many columns.

1 Answers

Using the example data I created below to emulate your data, we can convert our y variable into an indicator that is 1 when y isn't 0 and 0 otherwise. We can then use rleid() from the data.table package to create an identifier for each unique run of values in our y variable. If we remove the rows where y == 0, then we now basically have a group identifier for which rows correspond to which curve. We can then group_by() this identifier and get the within-curve maximum with summarise().

Note that this follows the OP in assuming that there are no value of exactly zero within a curve. In other words c(1,2,3,0,5,6,7,8,0,0,0) is two curves, not one.

library(dplyr)
library(ggplot2)
library(data.table)
set.seed(123)

# Example data
data <- data.frame(
  x = 1:50,
  y = c(runif(5), rep(0,5), 
        runif(5), rep(0,5),
        runif(5), rep(0,5),
        runif(5), rep(0,5), 
        runif(5), rep(0,5)))

# Show data
ggplot(data, aes(x=x, y=y)) + geom_line() + theme_bw()

# Get the maximum values between every run of zeroes
maxima <- data %>%
  mutate(curve = data.table::rleid(y != 0)) %>% 
  filter(y != 0) %>%
  group_by(curve) %>%
  summarise(peak = max(y))

print(maxima)
#> # A tibble: 5 x 2
#>   curve  peak
#>   <int> <dbl>
#> 1     1 0.940
#> 2     3 0.892
#> 3     5 0.957
#> 4     7 0.955
#> 5     9 0.994

# Get the mean
mean(maxima$peak)
#> [1] 0.9476986
Related