Неисправность определения шага / спайка для pandas графика данных? - PullRequest
0 голосов
/ 22 марта 2020

В настоящее время я пытаюсь узнать, как использовать данные CSV через pandas и matplotlib. У меня есть проблема, когда для набора данных, который явно имеет скачки в данных, мне нужно будет «очиститься», прежде чем что-то из него оценивать. Но у меня возникают трудности с пониманием того, как «обнаружить» пики на графике ...

Итак, набор данных, с которым я работаю, выглядит следующим образом:

df = pd.DataFrame({'price':[340.6, 35.66, 33.98, 38.67, 32.99, 32.04, 37.64, 
                            38.22, 37.13, 38.57, 32.4, 34.98, 36.74, 32.9,
                            32.52, 38.83, 33.9, 32.62, 38.93, 32.14, 33.09, 
                            34.25, 34.39, 33.28, 38.13, 36.25, 38.91, 38.9, 
                            36.85, 32.17, -2.07, 34.49, 35.7, 32.54, 37.91, 
                            37.35, 32.05, 38.03, 0.32, 33.87, 33.16, 34.74, 
                            32.47, 33.31, 34.54, 36.6, 36.09, 35.49, 370.51, 
                            37.33, 37.54, 33.32, 35.09, 33.08, 38.3, 34.32, 
                            37.01, 33.63, 36.35, 33.77, 33.74, 36.62, 36.74, 
                            37.76, 35.58, 38.76, 36.57, 37.05, 35.33, 36.41, 
                            35.54, 37.48, 36.22, 36.19, 36.43, 34.31, 34.85, 
                            38.76, 38.52, 38.02, 36.67, 32.51, 321.6, 37.82,
                            34.76, 33.55, 32.85, 32.99, 35.06]}, 
                   index = pd.date_range('2014-03-03 06:00','2014-03-06 22:00',freq='H'))

, который создает этот график:

as you can see there are major spikes in this graph

Итак, все эти значения находятся в диапазоне от 32 до 38. Я намеренно поместил очень большие числа в индексы [0, 30, 38 , 48, 82] для создания пиков на графике.

Теперь я пытался найти способ сделать так называемое «обнаружение шагов» на графике, и единственный реальный полезный ответ, который я нашел, это через этот вопрос здесь , и, используя его так, что я придумал этот общий код ...

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import argrelextrema

df = pd.DataFrame({'price':[340.6, 35.66, 33.98, 38.67, 32.99, 32.04, 37.64, 
                            38.22, 37.13, 38.57, 32.4, 34.98, 36.74, 32.9,
                            32.52, 38.83, 33.9, 32.62, 38.93, 32.14, 33.09, 
                            34.25, 34.39, 33.28, 38.13, 36.25, 38.91, 38.9, 
                            36.85, 32.17, -2.07, 34.49, 35.7, 32.54, 37.91, 
                            37.35, 32.05, 38.03, 0.32, 33.87, 33.16, 34.74, 
                            32.47, 33.31, 34.54, 36.6, 36.09, 35.49, 370.51, 
                            37.33, 37.54, 33.32, 35.09, 33.08, 38.3, 34.32, 
                            37.01, 33.63, 36.35, 33.77, 33.74, 36.62, 36.74, 
                            37.76, 35.58, 38.76, 36.57, 37.05, 35.33, 36.41, 
                            35.54, 37.48, 36.22, 36.19, 36.43, 34.31, 34.85, 
                            38.76, 38.52, 38.02, 36.67, 32.51, 321.6, 37.82,
                            34.76, 33.55, 32.85, 32.99, 35.06]}, 
                   index = pd.date_range('2014-03-03 06:00','2014-03-06 22:00',freq='H'))
# df.plot()
# plt.show()

threshold = int(len(df['price']) * 0.75)
maxPeaks = argrelextrema(df['price'].values, np.greater, order=threshold)
minPeaks = argrelextrema(df['price'].values, np.less, order=threshold)

df2 = df.copy()
price_column_index = df2.columns.get_loc('price')
allPeaks = maxPeaks + minPeaks
for peakList in allPeaks:
    for peak in peakList:
        print(df2.iloc[peak]['price'])

Но проблема в том, что он, кажется, только возвращает индексы 30 и 82, и он не захватывает большое значение в индексе 0, а также не захватывает ничего в отрицательных провалах. Хотя я очень уверен, что использую эти методы неправильно.

Теперь я понимаю, что для этой проблемы SPECIFI C я МОЖУ просто искать значения в столбце, который больше или меньше определенного значения, но Я имею в виду ситуации, связанные с 1000+ записями, в которых невозможно точно определить «самые низкие / самые высокие нормальные значения», и поэтому я просто хотел бы, чтобы обнаружение всплеска работало независимо от масштаба.

Итак у меня следующие вопросы:

1) Информация, которую я изучал об обнаружении шагов, казалась действительно очень плотной, и мне было очень трудно ее понять. Может ли кто-нибудь предоставить общее правило о том, как подходить к этим проблемам «обнаружения шагов»?

2) Существуют ли какие-либо публичные c библиотеки, которые позволяют выполнять эту работу с большей легкостью? Если да, то каковы они?

3) Как вы можете достичь тех же результатов, используя vanilla Python? Я был на многих рабочих местах, которые не позволяют устанавливать какие-либо другие библиотеки, заставляя принимать решения, которые не используют ни одну из этих полезных внешних библиотек, поэтому мне интересно, есть ли какая-нибудь формула / функция, которая могла бы быть написано для достижения аналогичных результатов ...

4) Какие еще подходы я мог бы использовать с точки зрения анализа данных при решении этой проблемы? Я читал кое-что о корреляции, стандартном отклонении, но на самом деле я не знаю, как можно использовать какой-либо из них для определения ГДЕ шипов ...

РЕДАКТИРОВАТЬ: также я нашел этот ответ также используя метод scipy find_peaks, но читая его do c Я не очень понимаю, что они представляют, и откуда взятые значения ... Любое разъяснение этого было бы очень признательно ...

1 Ответ

0 голосов
/ 22 марта 2020

Решение с использованием scipy.signal.find_peaks

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import find_peaks


df = pd.DataFrame({'price':[340.6, 35.66, 33.98, 38.67, 32.99, 32.04, 37.64, 
                            38.22, 37.13, 38.57, 32.4,  34.98, 36.74, 32.9,
                            32.52, 38.83, 33.9,  32.62, 38.93, 32.14, 33.09, 
                            34.25, 34.39, 33.28, 38.13, 36.25, 38.91, 38.9, 
                            36.85, 32.17, -2.07, 34.49, 35.7, 32.54, 37.91, 
                            37.35, 32.05, 38.03, 0.32,  33.87, 33.16, 34.74, 
                            32.47, 33.31, 34.54, 36.6,  36.09, 35.49, 370.51, 
                            37.33, 37.54, 33.32, 35.09, 33.08, 38.3,  34.32, 
                            37.01, 33.63, 36.35, 33.77, 33.74, 36.62, 36.74, 
                            37.76, 35.58, 38.76, 36.57, 37.05, 35.33, 36.41, 
                            35.54, 37.48, 36.22, 36.19, 36.43, 34.31, 34.85, 
                            38.76, 38.52, 38.02, 36.67, 32.51, 321.6, 37.82,
                            34.76, 33.55, 32.85, 32.99, 35.06]}, 
                   index = pd.date_range('2014-03-03 06:00','2014-03-06 22:00',freq='H'))


x = df['price'].values
x = np.insert(x, 0, 0)              # added padding to catch any initial peaks in data

# for positive peaks
peaks, _ = find_peaks(x, height=50) # hieght is the threshold value
peaks = peaks - 1

print("The indices for peaks in the dataframe: ", peaks)
print(" ")
print("The values extracted from the dataframe")
print(df['price'][peaks])

# for negative peaks
x = x * - 1    
neg_peaks, _ = find_peaks(x, height=0) # hieght is the threshold value
neg_peaks = neg_peaks - 1

print(" ")
print("The indices for negative peaks in the dataframe: ", neg_peaks)
print(" ")
print("The values extracted from the dataframe")
print(df['price'][neg_peaks])

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

Чтобы обойти это, я дополнил массив x дополнительным 0 в position 0 значение, которое вы вводите, зависит от вас,

x = np.insert(x, 0, 0)

Затем algorthim возвращает индексы , где находятся пиковые значения в массив в переменную peaks,

peaks, _ = find_peaks(x, height=50) # hieght is the threshold value

Поскольку я добавил начальное значение, я должен вычесть 1 из каждого из этих индексов,

peaks = peaks - 1

Теперь я могу использовать эти индексы для извлечения пиковых значений из кадра данных,

print(df['price'][peaks])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...