Найдите пики и основания графика и пометьте их - PullRequest
0 голосов
/ 01 сентября 2018
      df1
      Date           Topic  Return
      1/1/2010        A,B     -0.308648967
      1/2/2010        C,D     -0.465862046
      1/3/2010        E        0.374052392
      1/4/2010        F        0.520312204
      1/5/2010        G        0.503889198
      1/6/2010        H       -1.730646788
      1/7/2010        L,M,N    1.756295613
      1/8/2010        K        -0.598990239
      ......
      1/30/2010       z         2,124355
 Plot= df1.plot(x='Date', y='Return')

Как я могу найти самые высокие пики и самые маленькие впадины для этого графика и пометить эти специальные точки соответствующими Темами?

Ответы [ 2 ]

0 голосов
/ 01 сентября 2018

Это немного зависит от ваших определений "пика" и "впадины". Часто человек может заботиться о сглаженных пиках и впадинах для выявления широких тенденций, особенно при наличии шума. В случае, если вы хотите, чтобы каждый мелкозернистый провал или рост данных хотя (и если ваши строки отсортированы), вы можете немного обмануть с векторизованными подпрограммами от numpy.

import numpy as np

d = np.diff(df['Return'])
i = np.argwhere((d[:-1]*d[1:])<=0).flatten()
special_points = df['Topic'][i+1]

Первая строка с np.diff() сравнивает каждое возвращаемое значение со следующим возвращаемым значением. В частности, он их вычитает. В зависимости от вашего определения локального пика / впадины, у них будет свойство, что у вас есть только функция, которую вы ищете, если эти попарные различия чередуются по знаку. Рассмотрим следующий пик.

[1, 5, 1]

Если вы вычислите попарные разности, вы получите немного более короткий вектор

[4, -4]

Обратите внимание, что они чередуются в знаке. Следовательно, если вы умножите их, вы получите -16, что должно быть отрицательным. Это точное понимание, которое наш код использует для определения пиков и впадин. Уменьшение размера немного смещает вещи, поэтому мы смещаем найденные индексы на 1 (в блоке df['Topic'][i+1]).

Предостережения : Обратите внимание, что вместо строгого неравенства у нас есть <=. Это в случае, если у нас более широкий пик, чем обычно. Рассмотрим [1, 2, 2, 2, 2, 2, 1]. Возможно, строка 2 представляет пик и должна быть захвачена. Если это нежелательно, сделайте неравенство строгим.

Кроме того, если вас интересуют более широкие пики, этот алгоритм все еще не верен. Это достаточно быстро, но в целом он вычисляет только супернабор пиков / впадин. Рассмотрим следующее

[1, 2, 2, 3, 2, 1]

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

Дополнительно : Модуль scipy.signal имеет множество алгоритмов нахождения пиков, которые могут лучше подходить в зависимости от любых дополнительных требований, предъявляемых к вашим пикам. Модификация этого решения вряд ли будет такой же быстрой или чистой, как при использовании соответствующего встроенного процессора сигналов. Звонок на scipy.signal.find_peaks() может в основном повторить все, что мы здесь сделали, и у него есть больше вариантов, если они вам нужны. Другие алгоритмы, такие как scipy.signal.find_peaks_cwt(), могут быть более подходящими, если вам нужен какой-либо тип сглаживания или более сложные операции.

0 голосов
/ 01 сентября 2018
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# Take an example data
data = {"Date":["date{i}".format(i=i) for i in range(10)], "Topic":["topic{i}".format(i=i) for i in range(10)], "Return":[1,2,3,2,1,2,4,7,1,3]}
df = pd.DataFrame.from_dict(data)

dates = np.array(df["Date"].tolist())
returns = np.array(df["Return"].tolist())

# Calculate the minimas and the maximas
minimas = (np.diff(np.sign(np.diff(returns))) > 0).nonzero()[0] + 1 
maximas = (np.diff(np.sign(np.diff(returns))) < 0).nonzero()[0] + 1

# Plot the entire data first
plt.plot(dates, returns)
# Then mark the maximas and the minimas
for minima in minimas:
    plt.plot(df.iloc[minima]["Date"], df.iloc[minima]["Return"], marker="o", label=str(df.iloc[minima]["Topic"]))
for maxima in maximas:
    plt.plot(df.iloc[maxima]["Date"], df.iloc[maxima]["Return"], marker="o", label=str(df.iloc[maxima]["Topic"]))

plt.legend()
plt.show()

Пример кадра данных:

   Date   Topic  Return
0  date0  topic0       1
1  date1  topic1       2
2  date2  topic2       3
3  date3  topic3       2
4  date4  topic4       1
5  date5  topic5       2
6  date6  topic6       4
7  date7  topic7       7
8  date8  topic8       1
9  date9  topic9       3

Участок производит: enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...