You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
Convert from linear to log scale and back again
57 views (last 30 days)
Show older comments
I have include some example data.
%fit curve
[xData, yData] = prepareCurveData(log10(plot_data.xdata), plot_data.ydata);
ft = fittype( 'poly1' );
[fitresult, gof] = fit( xData, yData, ft ); %fit model to data
ci=confint(fitresult,0.95);
sp1=plot(fitresult,xData,yData,'ob'); %plot
I have distance on the x-axis, and sound pressure level on the y-axis. The distances are originally in metres, but when I fit a best fit line, the equation I use needs them to be logged. My issue is that I want to convert the x-axis back to metres so it's in a readable format. In addition, I'd like this to be on a logarithmic scale.
I tried the following:
xticklabels({'','','100','','','','','1000'}) %re-label x ticks in metres
set(gca,'XScale','log')
but the x-axis doesn't appear to be logged at all when I do this and the 1000m value disappears when I set the scale to log.
Answers (1)
Jon
on 23 Nov 2021
I think you can get what you want using MATLAB's semilogx function
21 Comments
Louise Wilson
on 23 Nov 2021
Edited: Louise Wilson
on 23 Nov 2021
I tried this:
semilogx(xData,yData)
hold on
plot(fitresult)
but now I get a line rather than scatter points, and the x axis is still not in metres.
Jon
on 23 Nov 2021
I don't have the curve fitting toolbox so I can't try your code exactly. It may be (although it would be surprising) that the curve fitting toolbox doesn't provide the option for making semilog plots, and in particular I'm not sure if MATLAB's semilogx will take a fitobject as an argument. You can always evaluate your fit object at the values of x of interest and put the result into an ordinary matlab vector and then use the semilogx function on that. Maybe someone who has the curve fitting toolbox can suggest a cleaner approach.
Jon
on 23 Nov 2021
regarding lines versus symbols you have to specify the linespec to use symbolds e.g.
semilogx(xData,yData,'o')
Jon
on 23 Nov 2021
assuming you can make a vector, let's call it yfit, with your fitted values (by evaluating your fit object at the points in xData) you could plot the original data and the fit using
semilogx(xData,yData,'o',xData,yfit,'-')
Louise Wilson
on 23 Nov 2021
Thank you. This solution plots the scale in log, but it doesn't help me to change the x axis units to a readable format.
Jon
on 23 Nov 2021
I'm not sure what you mean by a readable unit. Please attach a screenshot of your plot so I can see how it looks.
Jon
on 23 Nov 2021
So I think you are saying that you do not want to have 10^0 10^1 10^2 ... but instead 1,10, 100, ...
You can use this trick from https://www.mathworks.com/matlabcentral/answers/95023-how-do-i-change-the-x-axis-label-on-a-semilogx-plot-from-exponential-to-normal-format-in-matlab
semilogx(xData,yData,'o',xData,yfit,'-')
New_XTickLabel = get(gca,'xtick');
set(gca,'XTickLabel',New_XTickLabel);
Louise Wilson
on 23 Nov 2021
Edited: Louise Wilson
on 23 Nov 2021
Sorry, yes. The x axis is 10^(range) to give metres but instead I would like it to read in metres so 2=100m, 3=1000m. Then for the distances to be logged so you would see an increase of 10 x ticks from 100m to 1000m which would be logarithmically spaced.
Right now I have:
%fit curve
[xData, yData] = prepareCurveData(log10(acou_data.xdata), acou_data.ydata);
ft = fittype( 'poly1' );
[fitresult, gof] = fit( xData, yData, ft ); %fit model to data
ci=confint(fitresult,0.95);
%plot fit (plot1.png)
sp1=plot(fitresult,xData,yData,'og');
%you can convert the x axis to log and replace the tick marks (plot2.png)
xticklabels({'','','100','','','','','1000'}) %re-label x ticks in metres
set(gca,'XScale','log')
%...but the x axis is not logged correctly, the intervals between tick
%marks become constant.
%doesn't work:
semilogx(xData,yData,'o',xData,fitresult,'-')
Error using semilogx
Data must be numeric, datetime, duration or an array convertible to double.
Jon
on 23 Nov 2021
You get the error because fitresult is a curve fit obj not a vector of numeric values as semilogx expects. So you have to first calculate a vector of numeric values by evaluating your fit function at each x data point.
Unfortunately I don't have the curve fitting toolbox so I can't test this first to see if it works but I think this should be close:
yfit = fitresult(xData) % evaluate the fit function at the x data points
semilogx(xData,yData,'o',xData,yfit,'-')
New_XTickLabel = get(gca,'xtick');
set(gca,'XTickLabel',New_XTickLabel);
Louise Wilson
on 23 Nov 2021
Edited: Louise Wilson
on 23 Nov 2021
The code works, but it still doesn't answer my question. Did you understand what I mean about the x axis being in metres?
I tried to illustrate what I'm looking for, attached.
Jon
on 24 Nov 2021
I'm not clear about which code "works". Did you try the approach I suggested above calculating yfit and using semilogx? What did the plot look like from those lines of code? I'm pretty sure the plot you show is not the result of using semilogx
Louise Wilson
on 24 Nov 2021
Sorry to be confusing, it's plot 3 that is calculating using yfit and semilogx.
Jon
on 24 Nov 2021
Did you run exactly this code:
yfit = fitresult(xData) % evaluate the fit function at the x data points
semilogx(xData,yData,'o',xData,yfit,'-')
New_XTickLabel = get(gca,'xtick');
set(gca,'XTickLabel',New_XTickLabel);
I tried semilogx a number of times, it always gives me the log spacing that you are looking for. Maybe check to see if that plot is really the result of semilogx
Louise Wilson
on 24 Nov 2021
I'm sorry, I don't undertand. plot3 does have log spacing, but the units are wrong. Did you see my example plot?
Jon
on 24 Nov 2021
Once again, here is a simple example generating a plot with log spacing and units of the form 10,100,... rather than 10^1, 10^2
x = 1:1000
yfit = x.^2
semilogx(x,yfit),
get(gca,'xtick')
set(gca,'XTickLabel',New_XTickLabel)
I think you should be able to get something similar.

Louise Wilson
on 24 Nov 2021
I don't undertsand how to apply semilogx() to my data though.
I tried the code you suggested and it looks like this:

Jon
on 24 Nov 2021
As shown in the code I gave you, you evaluate to apply the output of fit at specific x values and assign them to an ordinary numeric vector use
yfit = fitresult(xData)
after that it is just an ordinary use of semilogx.
If you want to evaluate it at many x values in the range of interest you could use
xfit = linspace(min(xData),max(xData),1000)
yfit = fitresult(xfit)
semilogx(xData,yData,'o',xfit,yfit,'-')
New_XTickLabel = get(gca,'xtick');
set(gca,'XTickLabel',New_XTickLabel);
What part of the code isn't working for you?
Louise Wilson
on 24 Nov 2021
The code:
%Fit curve
[xData, yData] = prepareCurveData(log10(acou_data.xdata), acou_data.ydata);
ft = fittype( 'poly1' );
[fitresult, gof] = fit( xData, yData, ft ); %fit model to data
ci=confint(fitresult,0.95);
yfit = fitresult(xData)
semilogx(xData,yData,'o',xData,yfit,'-')
New_XTickLabel = get(gca,'xtick');
set(gca,'XTickLabel',New_XTickLabel);
works, but the plot (plot3), is not what I am looking for. So in my previous comment I included a screenshot of the Matlab window to show you that I have run it exactly as you included it, and the plot, plot3, is presented in the figure window.
Jon
on 25 Nov 2021
Edited: Jon
on 25 Nov 2021
Sorry, I don't have the curve fitting toolbox, so I can't try running your exact code to see if I can replicate the problem. I'm pretty sure the plot3.png that you attached is not the output from your code above, maybe some confustion in the files or something like that. For me using semilogx always produces a log spaced output and your plot3.png has a linear one. As I showed you a few post ago, when I make a ordinary numerical vectors xData, and yfit, and and run the last three lines of code above I get a log spaced x axis with labels 10,100,...
Just to be clear I will post the example again here.
x = 1:1000
yfit = x.^2
semilogx(x,yfit),
get(gca,'xtick')
set(gca,'XTickLabel',New_XTickLabel)
Which produces

Is this the kind of plot you are hoping to get? When you run the above code do you get the same plot I show above
If so, I can't really explain why you don't get the same result with your code and I guess I can't offer you any more help. If the example above, with made up data gives the plot you want, and when you assign the output using fitresult(xData) it doesn't work, then either there is some slight but important difference between our two codes, or maybe there is some aspect of using the curve fit toolbox that I am not aware of, but I'm mystified and frustrated I couldn't get this working for you. Sorry, I hope you can figure it out soon.
Louise Wilson
on 25 Nov 2021
Yes that is definitely the output. That is why I included a few comments back, the screenshot of running the code and the resultant figure, so you could believe it. I will start a new question.
See Also
Categories
Find more on Get Started with Curve Fitting Toolbox in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)