Asked by Camil Hamel
on 22 Feb 2011

I want to plot a graphic with data that varies over many order (from 10e-4 to 10e-8) with some positive and negative values. Using 'semilog' or 'set xaxis log' can't plot my negative values (witch is normal). When I plot with a normal scale, we don't really see the variability of my datas, we only see the very high values and all the small one are not very visible because there are to close to zero. What would you suggest me to be able to show all my data (even the negative values) and be able to show the variability (like on a log-scale graph). Thank you

*No products are associated with this question.*

Answer by Matt Tearle
on 24 Feb 2011

Accepted Answer

Oookay, I think I have it. If you're going to do this a lot, you may want to make yourself your own function. So, see if this does it for you:

function negsemilogx(x,y)

% Do log10 but keep sign xlog = sign(x).*log10(abs(x)); % Just to get axis limits plot(xlog,y,'o') % Get limits lims = xlim; wdth = diff(lims); % Wrap negative data around to positive side xlog(xlog<0) = xlog(xlog<0) + wdth; % Plot plot(xlog,y,'o') % Mess with ticks tck = get(gca,'XTick')'; % Shift those that were wrapped from negative to positive (above) back % to their original values tck(tck>lims(2)) = tck(tck>lims(2)) - wdth; % Convert to string, then remove any midpoint tcklbl = num2str(tck); tcklbl(tck==lims(2),:) = ' '; % Update tick labels set(gca,'XTickLabel',tcklbl)

Then to try it out:

>> x = -100:100; >> y = x.^3; >> negsemilogx(x,y)

Camil Hamel
on 24 Feb 2011

Excellent!

I had to work a little to get exactly what I wanted, but you put me on the right track.

Thanks a lot

Matt Tearle
on 25 Feb 2011

Out of curiosity, what was still missing/wrong?

Camil Hamel
on 25 Feb 2011

I changed the wdth selection by making it wdth=abs(min(negative data))+max(positive data). I put my zero at wdth/2. My graph look more smooth, there is not a so big area without data in the middle. I also customize all the tick part of the code making it automatic and adapted to my data. But I really just added a little to what you suggested me.

Log in to comment.

Answer by Richard
on 22 Feb 2011

When you choose "log" as the scale for an axis, Matlab either chooses to use log10(x) or -log10(-x) as the transform, depending on whether your data is in the positive or negative domain. As you've found, you can't have both at the same time because both halves map data into the [-inf inf] space.

You can play with your own transforms by transforming the data yourself and at the same time manipulating the XTickLabel property of the axes so that you show untransformed data values. For example, this splices the normal negative and positive transforms, (with the singularity at 0 untransformed):

x = -100:100; y = x.^3;

xt = x; xt(xt>0) = log10(1+xt(xt>0)); xt(xt<0) = -log10(1-xt(xt<0));

figure; ax = axes; plot(xt,y); set(ax, 'XTick', [-2 -1 0 1 2], ... 'XTickLabel', {'-100', '-10', '0', '10', '100'});

Noel
on 2 Jun 2016

Great answer. I didn't know about the transform (though it's quite obvious in hindsight). My problem has been dealing with small numbers in the log10 domain. In this case, if you simply try to transform the data using a sign(x)*log10(abs(x)), then there are problems, as the exponents are negative. Hence, the plot is pretty jacked because small negative numbers are changed into positive numbers and small positive numbers are changed into negative numbers. Anyways, thanks!

Log in to comment.

Answer by Matt Tearle
on 22 Feb 2011

Richard pretty much beat me to it. Here's a slightly more automated way to get the tick marks. However, unfortunately there's no TeX markup for tick labels, so you'll have to choose how you want them to appear -- plain exponent values (2, 3, 4, etc), values written out in full (100, 1000, etc), or some scientific notation (but without TeX markup, eg "10^3" or "1e3")

% Make some fake data n = 1:20; y = factorial(n); y(2:2:end) = -y(2:2:end); % Bad plot plot(n,y,'o')

% Transform ylog = sign(y).*log10(abs(y)); figure plot(n,ylog,'o')

% Do nothing else to get just exponents. Otherwise: yt = get(gca,'YTick')'; set(gca,'YTickLabel',num2str(sign(yt).*10.^abs(yt))) % Or, for scientific notation set(gca,'YTickLabel',strcat('10^',cellstr(num2str(abs(yt)))))

Log in to comment.

Answer by Matt Tearle
on 22 Feb 2011

Dumb question, but is there any reason you can't just look at the absolute values? ( `abs` in MATLAB)

Log in to comment.

Answer by Camil Hamel
on 22 Feb 2011

I can't look at the absolute value because I have to show and upward (positive) or downward (negative) flux. I tried with the absolute value and plotting with a different colour for negative value. The problem was that my mean data are between a 2.5% and a 97,5% that are sometime positive sometime negative. By taking the absolute value, my mean line values where not between the 2,5% and 97,5% lines because sometime the 2,5% was a negative value (large value). This value in absolute value was higher than the 97,5% witch was positive (small value).

Log in to comment.

Answer by Camil Hamel
on 23 Feb 2011

The figure I have now

x | x | x | x | | x | x | x | x | | | | | -8 -2 0 2 8 meaning 10^-8 10^-2 0 -10^-2 -10^-8 positive data |negative data __________________________ The figure I would like to have

| x | x | x |x x| x | x | x | | | | | | 2 8 -8 -2 meaning -10^-2 -10^-8 0 10^-8 10^-2 negative data|positive data

Thank you for the answers. I did as Matt said giving the first figure.

I hope you understand the figure I made with my attempt at drawing.

All my data in between -10^-8 , -10^-2 and 10^-2 , 10^-8. So I have to kind of get the value of the zero outside and having my maximum value (10^-8) in the centre of the figure. After that I could change the xticklabel as I want it.

I want to get a figure looking like the second one. Would that be possible and how?

Thank you very much

Log in to comment.

Answer by Kilbock Lee
on 11 Nov 2013

I think my way is easier using logical operation true false.

Assuming the matrix is P(x,y),

LogP=((P > 0).*log10(P))+(-(P<0).*log10(-P))

and then, plot LogP

First term converts positive values into log scale and Second term does the negative values

Log in to comment.

Answer by Alexandre HYAFIL
on 13 Apr 2017

Hi everyone,

I have just written a code that replots all the elements in your figure in negative/positive log-scale. It's for the Y axis but could be very simply adapted for the X axis: http://fr.mathworks.com/matlabcentral/fileexchange/62549-yscale-symlog

To use it: x = ... y = ... plot(x,y, ...); yscale_symlog;

Hope it will work for you!

Log in to comment.

Related Content

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn moreOpportunities for recent engineering grads.

Apply Today
## 0 Comments

Log in to comment.