Div
Div

Reputation: 121

Wrong coefficients from fit function in Matlab

I have a table looking like this:

x                 Line Name                                 
        -40 -30 -20 -10 0   10  20  30  40  50
-1500   NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
-1000   NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
0       NaN NaN NaN NaN NaN NaN NaN NaN NaN 700
1000    NaN NaN NaN NaN NaN NaN NaN NaN NaN 673
2000    NaN NaN NaN NaN NaN NaN NaN NaN 689 646
3000    NaN NaN NaN NaN NaN NaN NaN 694 662 NaN
4000    NaN NaN NaN NaN NaN NaN 696 668 636 NaN
5000    NaN NaN NaN NaN NaN 695 669 642 611 NaN
6000    NaN NaN NaN NaN 693 669 644 617 587 NaN
7000    NaN NaN NaN 691 666 643 619 593 563 NaN
8000    NaN NaN 691 665 641 619 595 569 NaN NaN
9000    NaN 691 664 639 616 595 572 547 NaN NaN
10000   691 664 639 615 592 571 550 525 NaN NaN
11000   664 638 614 591 569 549 528 503 NaN NaN
12000   638 613 590 567 546 527 507 483 NaN NaN
13000   612 589 566 545 525 506 486 NaN NaN NaN
14000   587 564 543 522 503 485 466 NaN NaN NaN
15000   562 541 520 500 482 465 446 NaN NaN NaN
16000   539 518 498 479 462 446 428 NaN NaN NaN
17000   516 496 477 459 442 427 409 NaN NaN NaN
18000   494 475 457 439 423 409 NaN NaN NaN NaN
19000   473 455 437 420 405 392 NaN NaN NaN NaN
20000   452 435 418 402 388 375 NaN NaN NaN NaN

I am able to graph a plot that looks like this:

enter image description here

From Left to right the blue lines represent "Line Name" -40 to 50.

Here is the exact code you can copy in:

%% Load data
Array6 =[NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
   NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
   NaN NaN NaN NaN NaN NaN NaN NaN NaN 700
   NaN NaN NaN NaN NaN NaN NaN NaN NaN 673
   NaN NaN NaN NaN NaN NaN NaN NaN 689 646
   NaN NaN NaN NaN NaN NaN NaN 694 662 NaN
   NaN NaN NaN NaN NaN NaN 696 668 636 NaN
   NaN NaN NaN NaN NaN 695 669 642 611 NaN
   NaN NaN NaN NaN 693 669 644 617 587 NaN
   NaN NaN NaN 691 666 643 619 593 563 NaN
   NaN NaN 691 665 641 619 595 569 NaN NaN
   NaN 691 664 639 616 595 572 547 NaN NaN
   691 664 639 615 592 571 550 525 NaN NaN
   664 638 614 591 569 549 528 503 NaN NaN
   638 613 590 567 546 527 507 483 NaN NaN
   612 589 566 545 525 506 486 NaN NaN NaN
   587 564 543 522 503 485 466 NaN NaN NaN
   562 541 520 500 482 465 446 NaN NaN NaN
   539 518 498 479 462 446 428 NaN NaN NaN
   516 496 477 459 442 427 409 NaN NaN NaN
   494 475 457 439 423 409 NaN NaN NaN NaN
   473 455 437 420 405 392 NaN NaN NaN NaN
   452 435 418 402 388 375 NaN NaN NaN NaN];

MakeMatrix = [-1500,-1000:1000:20000];
x = transpose([MakeMatrix;MakeMatrix;MakeMatrix;MakeMatrix;MakeMatrix;MakeMatrix;MakeMatrix;MakeMatrix;MakeMatrix;MakeMatrix]);        %transpose switches rows and columns=to match array dimentions

%% Plot
hold on
A=plot(x,Array6,'b*')     
grid on
grid minor

Here is the big question, and trust me I have been trying to solve this for a week now and have not gotten close. I want to separate the data of "Line Name" -50,-40 and -20 into vectors as seen here:

x1 = transpose([-1500,-1000:1000:20000]);     y1  = Array6(:,1);  %LineName-40
x2 = transpose([-1500,-1000:1000:20000]);     y2  = Array6(:,2);  %LineName-30
x3 = transpose([-1500,-1000:1000:20000]);     y3  = Array6(:,4);  %LineName-10

The problem was that the NaNs in my fit not being able to work, but this has been solved as seen below:

f = fittype('poly2');
DatumLine1Fit = fit(x1,y1,f, 'Exclude', isnan(y1));
DatumLine2Fit = fit(x2,y2,f, 'Exclude', isnan(y2));
DatumLine3Fit = fit(x3,y3,f, 'Exclude', isnan(y3));

Now I fetch the coeficcients and place them in a matrix:

DatumLine1Coeff = coeffvalues(DatumLine1Fit);
DatumLine2Coeff = coeffvalues(DatumLine2Fit);
DatumLine3Coeff = coeffvalues(DatumLine3Fit);

CoeffMatrix3x3 = transpose([DatumLine1Coeff;DatumLine2Coeff;DatumLine3Coeff]);

This gives the CoeffMatrix3x3 values as:

3.64801864801874e-07    3.46403596403601e-07    3.13873626373624e-07
-0.0348622377622380    -0.0333289210789212     -0.0307339285714285
1003.38694638695        962.893356643357        890.746978021977

However, this is the problem, this is the coefficients for coulombs(10,9 and 7), which is the opposite side of the matrix, and not coulombs(1,2 and 4) as indicated in my code?

The correct CoeffMatrix3x3 for coulombs(1,2 and 4) should be:

4.5e-07        3.393e-07                 3.25e-07                
-0.02775      -0.02815                  -0.02881                           
 700.6         744.1                     805.8

Here is some code to visually verify the wrong coeficcients are obtained(Note the fit lines are on lines 20,40 and 50...they should be on line -40,-30,-10):

DatumLineSet        = [-40 -30 -10];    % Left Original lines used for coefficient determination(Not need to be eavenly spaced)
AdditionalLineSet   = [-40: 10:-10];    % Left Additional lines to be plotted from the DatumLineSet
FitLine_XRange     = -5000:100:20000;   %X-Axis points created for the fit line to follow

 for i = 1:length(AdditionalLineSet),                                               %length= For vectors, the length is simply the number of elements

        % straight line coefficients 
        c02 = interp1(DatumLineSet,CoeffMatrix3x3(1,:),AdditionalLineSet(i));            %a from y=ax^2+bx+c
        c01 = interp1(DatumLineSet,CoeffMatrix3x3(2,:),AdditionalLineSet(i));            %b        
        c00 = interp1(DatumLineSet,CoeffMatrix3x3(3,:),AdditionalLineSet(i));            %c               

        % generate the line

       FitLine_YRange   = polyval([c02 c01 c00],FitLine_XRange);                     
       plot(FitLine_XRange,FitLine_YRange,'b');
    end

enter image description here

Please help. Many Thanks! You can find the correct coefficients with the matlab curve fitting app as explained in my comment.

Upvotes: 1

Views: 162

Answers (1)

Jim Quirk
Jim Quirk

Reputation: 626

I believe there is no problem with your code. The problem is in what you are comparing with at the end.

If I build and fit the first column of your data manually:

format shortg
x1=[10000:1000:20000]';
y1=[691;664;638;612;587;562;539;516;494;473;452];

coeffvalues(fit(x1,y1,'poly2'))'

ans =
3.648e-07
-0.034862
   1003.4

This is the same as your code is giving, suggesting that your 'correct' answer at the end which you are comparing to is the one that is wrong.

As an efficiency/readability issue, you should also change the line:

x = transpose([MakeMatrix;MakeMatrix;MakeMatrix;MakeMatrix;MakeMatrix;MakeMatrix;MakeMatrix;MakeMatrix;MakeMatrix;MakeMatrix]);        %transpose switches rows and columns=to match array dimentions

to

x = transpose(repmat(MakeMatrix,10,1));

or even

x = repmat(MakeMatrix,10,1)';

%% EDIT

After reviewing your new comment below, I believe I have discovered the problem:

After the plot at the top, you make the statement:

From Left to right the blue lines represent "Line Name" -40 to 50.

This is the incorrect statement that has been causing the confusion. This can be verified by comparing the first and last column of your table to the left and right curves of the plot:

In the table, the "-40" column has 11 integer values and the "50" column has 3 integer values.
In the plot, it is the right-most set of points that has 11 values and the left-most that has 3.

Upvotes: 1

Related Questions