# 在噪聲數據中查找局部最小值/最大值

temptimelist = Range[200]/10;
tempvaluelist = Sinc[#] &@temptimelist + RandomReal[{-1, 1}, 200]*0.02;


NoisyExtremaFinder = Function[{timeList, valueList, aroundRange},
(*NoisyExtremaFinder[] takes a pair of lists timeList_ and valueList_ and determines extrema in valueList_, returning a list containing the coordinates (as pairs of time_ and value_) of the minima as the first entry and the maxima as the second entry.

As the data is assumed to be noisy, we provide the option aroundRange_ to allow the user to determine the sensitivity of the search. Specifically, when aroundRange_=n, the function will compare each value with the preceding and subsequent n values to determine whether it is an extrema*)

extremaPosition =
[email protected][
Map[#, Partition[valueList, 2*aroundRange + 1, 1, {-(1 + aroundRange), 1 + aroundRange}, {}]] - valueList, 0.] &
(*extremaPosition[] is a custom function that determines the position of local Maxima or Minima in valueList_, with the sensitivity determined by the value of aroundRange. When aroundRange_=n, the function will compare each value with the preceding and subsequent n values to determine whether it is an extrema. You can either do extremaPosition[Max] or extremaPosition[Min] *)

extremaPoints =
[email protected]{timeList[[#]], valueList[[#]]} &@extremaPosition[#] &
(*extremaPoints[] is a custom function that determines the coordinates of local Maxima or Minima in valueList_

Custom Functions Used: extremaPosition[]*)

{extremaPoints[Min], extremaPoints[Max]}];


NoisyExtremaFinder[temptimelist, tempvaluelist, 10]; (*parameter "10" chosen by estimating the distance from peak to peak*)
ListPlot[Transpose[{temptimelist, tempvaluelist}],
Epilog -> {PointSize[Medium], Red, Point[extremaPoints[Min]], Green,
Point[extremaPoints[Max]]}, ImageSize -> 700]


rm-rf（在聊天中）也建議我在嘗試找到局部最小值/最大值之前先考慮平滑噪聲數據。但是，我擔心我可以通過平滑過程將不需要的工件添加到數據中。關於平滑，是否有一種常用於過濾實驗數據的算法？我查看的過濾器包括Savitsky-Golay過濾器和低通過濾器。

PS：我的數據集各有大約10,000個數據點。

## 最佳答案

(*Define data and noise*)
temptimelist = Range[200]/10;
data = Sinc[temptimelist];
noise = RandomReal[{-0.02, 0.02}, 200];

(* Define Wavelet for denoising *)
dwd = DiscreteWaveletTransform[data + noise, SymletWavelet[7], 6];
(* Use universal threshold *)
dwd = WaveletThreshold[dwd];
(*Get denoişed values*)
est = InverseWaveletTransform[dwd];

ListLinePlot[{data, est, (data + noise)}, PlotRange -> All]


Once you denoised the data you can find extreme values described in other answers.

findExtremaPos[list_List] :=
Module[{signs, extremaPos, minPos, maxPos},
signs = Sign[Differences[list]];
signs = signs //. {a___, q_, 0, z__} -> {a, q, q, z};
extremaPos = 1 + [email protected](Length /@ Split[signs]);
If[[email protected] == 1, minPos = extremaPos[[2 ;; -2 ;; 2]];
maxPos = extremaPos[[1 ;; -2 ;; 2]],
minPos = extremaPos[[1 ;; -2 ;; 2]];
maxPos = extremaPos[[2 ;; -2 ;; 2]]];
{minPos, maxPos}]

(*Evaluate extreme points*)
{minPos, maxPos} = findExtremaPos[est];

ListPlot[est, Joined -> True,
Epilog -> {PointSize[Large], Red, Point[{#, est[[#]]} & /@ minPos],
Blue, Point[{#, est[[#]]} & /@ maxPos]}, PlotRange -> All]


peaks = FindPeaks[est, .5]


{{2,1.0147576}，{6,0.94715655}，{78,0.13402331}，{143，     0.066621946}，{192,0.04389471}，{197,0.041374537}，{199，     0.060916925}}

ListPlot[{est, peaks}, Joined -> {True, False},
PlotStyle -> {Automatic, {PointSize[.01], Red}}, PlotRange -> All]