Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Mathematica has quite a nice ScalingFunctions option to BarChart, BubbleChart and the various financial charting functions, which simplifies log scaling, reverse scales and so on. Consider:

test = FoldList[0.85 #1 + #2 &, 0., 
  Abs@RandomVariate[NormalDistribution[0, 3], 25]]

{0., 1.40961, 4.59418, 9.49233, 11.4004, 9.93797, 11.0347, 11.0437, 
9.39412, 8.46501, 10.5416, 10.3413, 9.60696, 8.47968, 9.45521, 
9.44406, 12.3554, 15.3821, 17.8863, 15.5349, 17.2376, 18.3164, 
 18.5506, 16.459, 14.6381, 13.7955}

BarChart[test, Frame -> True]

enter image description here

BarChart[test, ScalingFunctions -> "Log", Frame -> True]

enter image description here

As has been previously noted on the site, the option actually works for ListPlot and ListLinePlot (but not DateListPlot) as well, even though this fact is not documented.

ListLinePlot[test, ScalingFunctions -> {"Log10", "Reverse"}]

enter image description here

However that breaks down where there is a frame. The tick labels (FrameTicks) are now the rescaled values, not the original values. The data are correctly rescaled.

ListLinePlot[test, ScalingFunctions -> {"Log10", "Reverse"}, Frame -> True]

enter image description here

Obviously the undocumented insertion of this functionality into ListPlot and ListLinePlot only affected Ticks and not FrameTicks.

Is there any way to get the correct tick labels back?
Even better, is there a reasonably straightforward way to use OptionValue[ScalingFunctions] to ensure that custom tick mark placement is correct when the data have been rescaled like this?

share|improve this question
1  
When I specify PlotRange it never seems to take ScalingFunction into account, even in the documented uses. I could imagine that PlotRange is used in the FrameTicks calculation. If this turns out to be too hard, maybe you can use this work-around: BarChart[test, Frame -> True, ScalingFunctions -> "Reverse", Joined -> Automatic, ChartStyle -> Directive[Red, FaceForm[], EdgeForm[]] ] However you can only apply ScalingFunctions to the y axis here. –  Jens Jun 30 '12 at 5:12
    
@Jens that's very clever, thank, but unfortunately only it works if you only have one series. In my actual application, I have a set of custom functions to plot various kinds of plots with highly customised settings, so that they fit nicely in my multipanel graphs –  Verbeia Jun 30 '12 at 5:19
1  
FWIW, when thinking of a similar application, :) , I put the undocumented use of ScalingFunction in the too hard basket and went with a switch to ListLogPlot and similar. –  Mike Honeychurch Jun 30 '12 at 8:28
add comment

2 Answers

Extracting tick locations with AbsoluteOptions appears promising, despite error messages.

g = ListLogPlot[test];

Show[g, Frame -> True, FrameTicks -> AbsoluteOptions[g, Ticks][[1, 2]]]

Mathematica graphics

I am using ListLogPlot as a proxy for ScalingFunctions. Again, v7 works differently so I see little point in me carefully tweaking this method, but I think this shows that it should be possible.

share|improve this answer
    
Sorry, this was the one that the comment " It's a good idea, but if one is drawing a ListLogPlot anyway one may as well just do that instead of using ScalingFunctions." was about –  Verbeia Jun 30 '12 at 7:44
1  
@verbeia With mr.wiz at v7 this is the closest he could get to answering with a tested answer. The intention is to replace the ListLogPlot with your plot and ScalingFunction. –  Sjoerd C. de Vries Jun 30 '12 at 10:07
add comment

Version 7 doesn't support ScalingFunctions so I cannot test this, and I suppose that Overlay (also absent from v7) may work better.

Nevertheless here is one approach that may work with modification:

ListLinePlot[
  test,
  ScalingFunctions -> {"Log10", "Reverse"},
  ImagePadding -> 20, AxesOrigin -> #
] & /@ {{0, 0}, {Length@test, Max@test}};

ImageCompose @@ %

enter image description here

Here it is with Overlay: not pixelated, but still some clashes of ticks.

Overlay[ListLinePlot[test, ScalingFunctions -> {"Log10", "Reverse"}, 
ImagePadding -> 20, AxesOrigin -> #] & /@ {{0, 0}, {Length@test, 
Max@test}}]

enter image description here

It turns out that you need to scale the values of the AxesOrigin according to the scaling function you want to use. In this case, one must Log the x-coordinate and reverse the sign of the y-coordinate.

Overlay[ListLinePlot[test, ScalingFunctions -> {"Log", "Reverse"}, 
    PlotRange -> All, ImagePadding -> 20, AxesOrigin -> #] & /@ {{0, 
    0}, {Log@Length@test, -Max[test]}}]

enter image description here

share|improve this answer
    
+1: certainly food for thought, but there are some strange overlaps. –  Verbeia Jun 30 '12 at 7:07
    
@Verbeia thanks for the image. I am surprised to see that the lower "frame" is missing; can you tell why? Also, I posted another answer that is rough but promising. –  Mr.Wizard Jun 30 '12 at 7:09
    
@Verbeia it just hit me: with "Reverse" working that should probably be Min@test -- would you try that, please? –  Mr.Wizard Jun 30 '12 at 7:10
    
Yes, but I realised that isn't the issue - one actually has to rescale the points for the AxisOrigin: {Log@Length@test, -Max[test]}} in this case. Given that, it will probably be easier for me to just catch the value of the option and change the head of the plotting function to ListLogPlot or ListLogLogPlot depending on its value. The tick labels inside the plot area would also have to be fixed. –  Verbeia Jun 30 '12 at 7:19
    
@Verbeia I agree this is not looking good. Do you think my second answer is more promising? –  Mr.Wizard Jun 30 '12 at 7:27
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.