Как определить диапазон точек данных между минимумом и максимумом в кадре данных в R? - PullRequest
1 голос
/ 27 февраля 2020

Моя измеряемая переменная V1 следует циклам: она поднимается, чтобы достичь максимума, и понижается, чтобы достичь минимума. Я называю «циклом» диапазон точек данных между двумя последовательными максимумами (цикл 1 - максимум 1 - минимум 1 - максимум 2, цикл 2 - максимум 2 - минимум 2 - максимум 3). Минимумы и максимумы каждого цикла различны.

Мои два вопроса:

  1. как определить диапазон точек данных в V1, соответствующих каждому циклу?

  2. как извлечь все минимумы и все максимумы в V1?

Я использовал ggplot для определения моих минимумов и максимумов, используя stat_peaks() и stat_valleys(). Я хочу найти способ сделать это без построения графика, применить его ко многим фреймам данных.

plot with highlighted minima and maxima

library(ggplot2)
library(ggpmisc)
#I plotted my data to visualize the minima (in yellow) and maxima (in blue) with stat_peaks and stat_valleys.
plot <- ggplot(df, aes(x=V0, y=V1))+
  geom_point()+
  stat_peaks(color="yellow", span=61)+
  stat_valleys(color="blue", span=101)
#I used the ggplot_build function to extract the values of the highlighted peaks and valleys.
pb <- ggplot_build(plot)

Я хотел определить 10 самых больших значений в pb для которого colour == "yellow" и 10 самых низких значений в pb, для которых colour == "blue", но это не работает, потому что pb не является фреймом данных.

dput(df[1:200, c(1,2)]) 
structure(list(V0 = c(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 
0.9, 1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.1, 
2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3, 3.1, 3.2, 3.3, 3.4, 
3.5, 3.6, 3.7, 3.8, 3.9, 4, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 
4.8, 4.9, 5, 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.9, 6, 
6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8, 6.9, 7, 7.1, 7.2, 7.3, 
7.4, 7.5, 7.6, 7.7, 7.8, 7.9, 8, 8.1, 8.2, 8.3, 8.4, 8.5, 8.6, 
8.7, 8.8, 8.9, 9, 9.1, 9.2, 9.3, 9.4, 9.5, 9.6, 9.7, 9.8, 9.9, 
10, 10.1, 10.2, 10.3, 10.4, 10.5, 10.6, 10.7, 10.8, 10.9, 11, 
11.1, 11.2, 11.3, 11.4, 11.5, 11.6, 11.7, 11.8, 11.9, 12, 12.1, 
12.2, 12.3, 12.4, 12.5, 12.6, 12.7, 12.8, 12.9, 13, 13.1, 13.2, 
13.3, 13.4, 13.5, 13.6, 13.7, 13.8, 13.9, 14, 14.1, 14.2, 14.3, 
14.4, 14.5, 14.6, 14.7, 14.8, 14.9, 15, 15.1, 15.2, 15.3, 15.4, 
15.5, 15.6, 15.7, 15.8, 15.9, 16, 16.1, 16.2, 16.3, 16.4, 16.5, 
16.6, 16.7, 16.8, 16.9, 17, 17.1, 17.2, 17.3, 17.4, 17.5, 17.6, 
17.7, 17.8, 17.9, 18, 18.1, 18.2, 18.3, 18.4, 18.5, 18.6, 18.7, 
18.8, 18.9, 19, 19.1, 19.2, 19.3, 19.4, 19.5, 19.6, 19.7, 19.8, 
19.9, 20), V1 = c(32.56, 31.97, 29.08, 27.34, 25.34, 22.58, 
20.93, 17.93, 14.65, 12.2, 9.88, 7, 5.52, 3.96, 3.26, 2.76, 3.23, 
3.38, 3.5, 3.67, 4.24, 7.1, 9.94, 14.58, 17.57, 21.64, 23.83, 
27.28, 29.48, 33.13, 34.37, 36.74, 37.13, 36.52, 35.87, 36, 35.49, 
33.81, 32.89, 30.47, 29.87, 27.84, 25.83, 23.31, 21.39, 18.63, 
16.42, 12.9, 10.6, 7.43, 5.95, 4.52, 3.76, 2.61, 2.94, 3.42, 
2.89, 3.38, 3.64, 4.2, 5.74, 9.48, 12.71, 17.46, 19.76, 23.93, 
27.46, 31.99, 34.07, 40.37, 46.48, 42.89, 48.33, 56.99, 47.16, 
43.53, 39.86, 37.48, 30.36, 26.01, 23.03, 20.57, 15.92, 13.87, 
11.61, 8.58, 6.52, 4.79, 3.88, 2.9, 2.94, 3.22, 3.45, 3.66, 3.89, 
6.01, 8.37, 12.83, 15.06, 18.68, 21.2, 24.12, 26.97, 28.48, 26.69, 
37.06, 40.15, 39.36, 35.73, 35.61, 35.83, 35.14, 31.55, 30.05, 
25.34, 24.24, 23.4, 21.09, 18.32, 16.04, 13.18, 10.07, 8.23, 
5.78, 4.71, 3.44, 3.48, 3.71, 3.72, 3.9, 4.56, 6.93, 9.3, 14.04, 
14.66, 16.25, 18.43, 20.76, 21.86, 23.87, 26.63, 24.85, 29.98, 
26.67, 26.99, 27.36, 25.08, 25.24, 26.48, 24.1, 22.66, 22.28, 
23.29, 21.87, 21.02, 19.53, 22.75, 22.04, 20.64, 19.05, 19.4, 
21, 18.93, 25.38, 23.59, 21.48, 21.9, 23.75, 23.38, 25.06, 25.2, 
26.38, 25.22, 28.62, 27.38, 34.16, 35.94, 34.03, 28.95, 24.33, 
24.76, 25.56, 24.96, 21.99, 23.53, 23.76, 24.5, 22.39, 23.01, 
23.42, 24, 22.65, 21.44, 22.15, 21.72, 18.46, 17.65, 15.34, 16.11, 
14.93)), row.names = c(NA, 200L), class = "data.frame")

Ответы [ 2 ]

1 голос
/ 27 февраля 2020

Вы можете добавить переменную к вашему фрейму данных, которая довольно легко помечает максимумы и минимумы, используя следующую строку:

df$is_min_max <- c(FALSE, diff(as.numeric(diff(df$V1) > 0)) != 0, FALSE)

Я объясню, как это работает:


Вы можете узнать разницу между последовательными точками в ваших данных, выполнив

diff(df$V1)

, чтобы вы могли увидеть, где ваши данные идут вверх или вниз, выполнив

as.numeric(diff(df$V1) > 0)

, что даст Вы 1 между двумя точками на восходящем градиенте и 0 на нисходящем градиенте. Поэтому, если вы сделаете

diff(as.numeric(diff(df$V1) > 0))

Вы получите +1 или -1 в точках, где меняется направление.

Так что если вы сделаете:

diff(as.numeric(diff(df$V1) > 0)) != 0

Вы получите логический вектор точек, которые являются локальными максимумами и минимумами. Обратите внимание, что начальная и конечная точки были удалены, потому что у нас двойная диффузия. Поэтому нам нужно добавить FALSE на любом конце:

c(FALSE, diff(as.numeric(diff(df$V1) > 0)) != 0, FALSE)

Таким образом, мы могли бы добавить это к вашему фрейму данных как

df$is_min_max <- c(FALSE, diff(as.numeric(diff(df$V1) > 0)) != 0, FALSE)

Вы не включили фактическое данные в вашем примере, поэтому я покажу пример здесь, используя простую синусоидальную волну:

df <- data.frame(x = seq(1, 20, 0.1), V1 = sin(seq(1, 20, 0.1)))
plot(df$x, df$V1)

enter image description here

И теперь мы можем просто найти наш локальный максимумы и минимумы ...

df$is_min_max <- c(FALSE, diff(as.numeric(diff(df$V1) > 0)) != 0, FALSE)

И нанесите их на график:

points(df$x[df$is_min_max], df$V1[df$is_min_max], col = "red", cex = 3 )

Обратите внимание, что это будет отображаться каждые измените направление, поэтому, если в ваших данных есть локальные колебания, вы также найдете максимумы и минимумы. Удалить их можно, но немного сложнее.

Создано в 2020-02-27 пакетом Представить (v0.3.0)

0 голосов
/ 27 февраля 2020

Координаты пиков и долин содержатся в pb:

Пики в

pb$data[[2]]
  xintercept yintercept label    x         y PANEL group x.label y.label shape colour size fill alpha stroke
1        7.9  0.9989413   7.9  7.9 0.9989413     1    -1     7.9  0.9989    19 yellow  1.5   NA    NA    0.5
2       14.1  0.9993094  14.1 14.1 0.9993094     1    -1    14.1  0.9993    19 yellow  1.5   NA    NA    0.5

Долины в

pb$data[[3]]
  xintercept yintercept label  x          y PANEL group x.label y.label shape colour size fill alpha stroke
1         11 -0.9999902    11 11 -0.9999902     1    -1      11      -1    19   blue  1.5   NA    NA    0.5

Обратите внимание, что порядок элементов списка может меняться в зависимости от порядка вызовов функций ggplot ( layer ).

Также обратите внимание, что выборочные данные, предоставленные OP, слишком малы по отношению к заданным диапазонам в звонках stat_peaks(color="yellow", span=61) и stat_valleys(color="blue", span=101), соответственно

Поэтому я использовал пример данных из Ответ Аллана :

df <- data.frame(V0 = seq(1, 20, 0.1), V1 = sin(seq(1, 20, 0.1)))

, который выделяет два пика и одну долину с использованием кода OP:

library(ggplot2)
library(ggpmisc)
plot <- ggplot(df, aes(x=V0, y=V1))+
  geom_point()+
  stat_peaks(color="yellow", span=61)+
  stat_valleys(color="blue", span=101)
plot

enter image description here

...