I am trying to add a trendline to a semilogx
plot but cannot succeed. I want the trendline between y(17)
and y(20)
, but it is not plotted as a straight line.
This is my code:
%// Define equation.
x = [90868 68151 45434 34076 27261 13631 6816 3408 2273 1948 1705 1137 853 683 569 455 342 274 228 190];
y = [3680 3723 3800 3866 3920 4103 4250 4320 4340 4344 4350 4364 4373 4379 4384 4393 4398 4402 4405 4407];
%// Plot it
semilogx(x,y, 'bo-', 'LineWidth', 3);
grid on;
%// Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
%// Give a name to the title bar.
set(gcf,'name','Demo by ImageAnalyst','numbertitle','off')
%// Fit the y data range with a line (limitedRange).
limitedRange = 17:20;
coeffs = polyfit(x(limitedRange), y(limitedRange), 1);
xFitting = linspace(200, 90000, 50);
yFitted = polyval(coeffs, xFitting);
%// Plot the fitted line over the specified range.
hold on;
plot(xFitting, yFitted, 'ro-', 'LineWidth', 2);
legend('Original Data', 'Line Fit');
How do I make the trendline appear as a line?
There should be no complaints for polyfit
here, it works.
This is your plot:
Everything makes sense. The reason your line gets distorted is because your x-axis has a logarithmic scale (if you're plotting a line ax+b
on a logarithmic x-scale, you'll see it as a alogx+b
curve).
To see it as a line on a logarithmic x-axis, you will need to introduce the appropriate "inverse" distortion. In your case, the trendline should be computed like so:
limitedRange = 17:20;
coeffs = polyfit(log10(x(limitedRange)), y(limitedRange), 1); %// Note the log10
xFitting = linspace(200, 90000, 50);
yFitted = polyval(coeffs, log10(xFitting)); %// Note the log10
This is not all. In a logarithmic scale low x-coordinates tend to be more spaced out, and the trendline circles will be more dense at the higher values of the x-axis. To negate that, you need the points in xFitting
to be exponentially spaced on a linear scale, so that they would appear linearly spaced on the logarithmic scale, for instance:
xFitting = 10 .^ (1:.1:5);
or use the built-in logspace
function:
xFitting = logspace(1, 5, 50);
The final code for computing the trendline should be:
limitedRange = 17:20;
coeffs = polyfit(log10(x(limitedRange)), y(limitedRange), 1);
xFitting = logspace(1, 5, 50);
yFitted = polyval(coeffs, log10(xFitting));
And this should give you the following plot:
Again, keep in mind that this is a logarithmic scale!
Hope this helps :)