我有两个数组,波峰和波谷,我想找到波峰和波谷,然后以交替的方式将它们连接起来,这样就不会有两个或更多的波峰/波谷连续出现,例如:
Highs = [107165., 107095., 107000., 107045., 106980., 106940., 106890.,
106740., 106565., 106615., 106375., 106440., 106445., 106290.,
106245., 106270., 106075., 105990., 106260., 106395., 106315.,
106080., 106180., 106305., 106265., 106180., 106360., 106260.,
106110., 106070.]
Lows = [106815., 106845., 106905., 106920., 106850., 106850., 106565.,
106460., 106380., 106305., 106250., 106280., 106155., 106035.,
106055., 105960., 105915., 105875., 105760., 106110., 105945.,
105820., 105865., 106095., 106020., 105925., 106045., 106020.,
105925., 105880.]应用高斯滤波器来平滑数据
from scipy.ndimage.filters import gaussian_filter1d
gauH = gaussian_filter1d(Highs, 1)
gauL = gaussian_filter1d(Lows, 1)在高峰和低谷中寻找高峰
iCeils = (np.diff(np.sign(np.diff(gauH))) < 0).nonzero()[0] + 1 # Ceils index
iFloors = (np.diff(np.sign(np.diff(gauL))) > 0).nonzero()[0] + 1 # Floors index现在我需要对它们进行连接和排序,找出一行中有多个峰/谷,并从数组中删除低位/高位。目前我是这样做的:
将1赋值给山峰,将0赋值给山谷
iCeils = np.concatenate([np.reshape(iCeils, (len(iCeils), 1)), np.reshape(np.ones(len(iCeils)),
(len(iCeils), 1))], axis = 1).astype(int)
iFloors = np.concatenate([np.reshape(iFloors, (len(iFloors), 1)), np.reshape(np.zeros(len(iFloors)),
(len(iFloors), 1))], axis = 1).astype(int)在pandas数据帧中连接两者并进行排序
iCF = pd.DataFrame(np.concatenate([iCeils, iFloors], axis = 0), columns = ['Val', 'kind']).sort_values(['Val'])对于上下文,它给出了类似这样的东西:
iCF = pd.DataFrame([[17, 0],
[19, 1],
[21, 0],
[25, 0],
[26, 1]], columns = ['Val', 'kind'])一行中有2个谷,值分别为21和25,Low21 = 105820 < Low25 = 105925,因此从dataframe中删除25,并获得以下结果:
iCF = pd.DataFrame([[17, 0],
[19, 1],
[21, 0],
[26, 1]], columns = ['Val', 'kind'])现在我可以遍历整个数据帧,检查列'kind‘是否连续具有相同的值,并删除最高的谷和最低的峰值,但我不确定循环是否会更有效,有什么建议吗?
Edit1,为了更清楚,我想去掉蓝色圆圈中的圆点

Edit2,我打错了哪个Val应该被移除
发布于 2020-06-23 00:20:02
下面是另一种方法,先使用scipy.signal,然后进行列表理解。
编辑:用整个数据集(25466行)替换测试数据。整个代码每个循环需要3.67秒±364毫秒(平均值±标准。dev.共运行7次,每个循环1次)在我的机器上运行,包括所有导入和绘图。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.signal import find_peaks
from collections import Counter
dataset=pd.read_csv('/path/to/WIN205.csv', delimiter = ':', header = 0)
Highs=np.array(dataset.High)
Lows=np.array(dataset.Low)
#find peaks by simple comparison of neighboring value
peaks, _ = find_peaks(Highs)
plt.plot(Highs,color='gray', zorder=1)
#invert Lows to transform
Lows_inv=Lows*(-1)
valleys, _ = find_peaks(Lows_inv)
#plot the results
plt.figure()
plt.subplot(121)
plt.plot(Highs,color='gray', zorder=1)
plt.scatter(peaks, Highs[peaks], color='red', marker='x', s=100, zorder=2)
plt.title('Peaks',fontsize=18)
plt.xlabel('Values (n°)',fontsize=15)
plt.ylabel('Highs (?)',fontsize=15)
plt.subplot(122)
plt.plot(Lows,color='gray', zorder=1)
plt.scatter(valleys, Lows[valleys], color='red', marker='x', s=100, zorder=2)
plt.title('Valleys',fontsize=18)
plt.xlabel('Values (n°)',fontsize=15)
plt.ylabel('Lows (?)',fontsize=15)
#combine peaks and valleys
df_peaks=pd.DataFrame({'category':np.ones(len(peaks)), 'height': Highs[peaks]},index=peaks)
df_valleys=pd.DataFrame({'category':np.zeros(len(valleys)), 'height': Lows[valleys]}, index=valleys)
df_pv=pd.concat([df_peaks,df_valleys], sort=True).sort_index()
#split df by blocks of consecutive same categories
df_pv['block'] = (df_pv.category.shift(1) != df_pv.category).astype(int).cumsum()
#count number of values in each block
blocks=Counter(df_pv['block'])
def filter_outputs(block_id, nb_vals):
#work on blocks with consecutive same categories
if nb_vals>1:
df_block=df_pv[df_pv.block==block_id]
#check if peak or valley block and keep max if peak, min if valley
if df_block.category.iloc[0]==1:
indxs_to_keep=[np.where(df_pv.height==np.nanmax(df_block.height))[0][0]]
else:
indxs_to_keep=[np.where(df_pv.height==np.nanmin(df_block.height))[0][0]]
#keep other blocks unchanged
else:
indxs_to_keep=[np.where(df_pv.block==block_id)[0]]
return indxs_to_keep
#find all indexes to keep
indxs_to_keep=[filter_outputs(block_id, nb_vals) for block_id, nb_vals in blocks.items()]
#and keep them!
df_pv_filtered=df_pv.reset_index().iloc[[val for sublist in indxs_to_keep for val in sublist]]https://stackoverflow.com/questions/62517288
复制相似问题