Search code examples
regressionmapletrigonometry

Sine regression in Maple


Hi I am struggling to perform sine regression in Maple, I have tried using code on the internet but it hasnt worked. Any help would be appreciated, thanks.

My data set is:

  xy2 := [8.00, -.506679048120256], [8.08, 0.281910754667817e-1], [8.16,   .559664265569177], [8.24, 1.01070100324046], [8.32, 1.31611672505376], [8.40, 1.43196427035055], [8.48, 1.34023337273233], [8.56, 1.05272193513947], [8.64, .611568467681354], [8.72, 0.811397528142090e-1], [8.80, -.461438501129773], [8.88, -.937510436115816], [8.96, -1.27829712008967], [9.04, -1.43481210421374], [9.12, -1.38382085374637], [9.20, -1.13084364570752], [9.28, -.712970794810407], [9.36, -.191272835454596], [9.44, .358331090663093], [9.52, .856136430555551], [9.60, 1.23021604773045], [9.68, 1.42679944926732], [9.76, 1.41736947469857], [9.84, 1.20128507880053], [9.92, .810092632128225], [10.00, .301065940880780], [10.08, -.251648449233878], [10.16, -.767849176869750], [10.24, -1.17292120742612], [10.32, -1.40861259493884], [10.40, -1.44110418232058], [10.48, -1.26379776830055], [10.56, -.902269772395664], [10.64, -.409554051221942], [10.72, .142501522971709], [10.80, .673734976975030], [10.88, 1.10731447772044], [10.96, 1.38084402685540], [11.04, 1.45522841363022], [11.12, 1.31817268904005], [11.20, .988929300957682], [11.28, .515897968446476], [11.36, -0.318624454182872e-1], [11.44, -.574750512030218], [11.52, -1.03419534660239], [11.60, -1.34402349055817], [11.68, -1.45994449557100], [11.76, -1.36423262002034], [11.84, -1.06956673456288], [11.92, -.619350106423691], [12.00, -0.793958770633476e-1], [12.08, .471761289512621], [12.16, .954294022860301], [12.24, 1.29864164214636], [12.32, 1.45551063055783], [12.40, 1.40182920346040], [12.48, 1.14373164965961], [12.56, .719231990114759], [12.64, .190472087224845], [12.72, -.365570174515493], [12.80, -.868296154301247], [12.88, -1.24516814950451], [12.96, -1.44215768668732], [13.04, -1.43084370975717], [13.12, -1.21101958959963], [13.20, -.814918996519041], [13.28, -.300617712320080], [13.36, .256936910993194], [13.44, .776860662411496], [13.52, 1.18406604455853], [13.60, 1.42009393305225], [13.68, 1.45118920522256], [13.76, 1.27106808636091], [13.84, .905832007489113], [13.92, .409125471244190], [14.00, -.146591404838158], [14.08, -.680632305076273], [14.16, -1.11580154033477], [14.24, -1.38954335200116], [14.32, -1.46281456021820], [14.40, -1.32355502489098], [14.48, -.991432071017881], [14.56, -.515321026695257], [14.64, 0.352425325998812e-1], [14.72, .580250581641171], [14.80, 1.04085183402835], [14.88, 1.35075391063922], [14.96, 1.46571651564137], [15.04, 1.36819902679830], [15.12, 1.07121797171521], [15.20, .618559572280749], [15.28, 0.764165939267409e-1], [15.36, -.476354929024263], [15.44, -.959710193024244], [15.52, -1.30400243735277], [15.60, -1.45998995251031], [15.68, -1.40476029253913], [15.76, -1.14472632247135], [15.84, -.718223841180242], [15.92, -.187706295906662], [16.00, .369587917409398], [16.08, .872888602357739], [16.16, 1.24959729981774], [16.24, 1.44574029144576], [16.32, 1.43304191884974]} 

Solution

  • Optimization routines do not know what the data looks like and when supplied with as much data as you have, it may mistake the sine regression for e.g. white noise and the approximation algorithm is likely to fail. We, however, have an easy time seeing patterns and can help the routine, which is necessary in this case.

    Let us start by plotting the data:

    with(plots):
    pointplot({xy2});
    

    Data plot

    A human can easily see the pattern going on here. But a naive implementation of a fit gives a bad result:

    ## Split data
    X := [seq(xy2[i][1], i = 1..numelems({xy2}))]:
    Y := [seq(xy2[i][2], i = 1..numelems({xy2}))]:
    ## Fit a sine curve to data
    fit := Statistics:-NonlinearFit(a*sin(b*x+c)+d,X,Y,x);
    ## Plot
    fitplot := plot(fit,x = min(X)..max(X),view = min(Y)..max(Y),legend = evalf(fit,4)):
    display(pointplot(X,Y),fitplot);
    

    Output:

    fit := 0.0099 * sin(28.6850 * x - 365.4958) + 0.0448
    

    Bad fit

    We can restrict the optimization routine to ranges on the parameters (e.g. a seems to be between 1 and 2). Good initial guesses can also be important when doing optimization. Fiddling around with parameterranges and initialvalues gives a nice convergence.

    fit := Statistics:-NonlinearFit(a*sin(b*x+c)+d,X,Y,x,
                                    parameterranges = [a=1..2,b = 1..10],
                                    initialvalues = [a = 1.5,b = 5]);
    ## Plot
    fitplot :=plot(fit,x = min(X)..max(X),view = min(Y)..max(Y),legend = evalf(fit,4)):
    display(pointplot(X,Y),fitplot);
    

    Output

    fit := 1.457*sin(4.790*x+11.58)-0.5483e-3
    

    Good fit