**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

6 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.

##### 0 Comments

### 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

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

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

Jon
on 23 Nov 2021

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

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

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

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

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

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

### See Also

### 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.