4
$\begingroup$

My question is a lot similar to the one about Custom Scaling of x-axis in ListPlot, however since I am using ListLogPlot, the option of ScalingFunctions does not work. I have a data set:

data={{0.05, Around[1.2, 0.01]}, {2.05, Around[1.56, 0.01]}, {4.05,Around[2.8974, 0.0237]}, {5.05, Around[3.51, 0.02]}, {6.05, Around[3.98, 0.02]}, {8.05, Around[4.3068, 0.0287]}, {10.05, Around[4.42, 0.02]}, {15.05, Around[4.81, 0.0303]}, {25.05, 
  Around[5.34, 0.01]}, {35.05, Around[6.486, 0.035]}, {45.05, Around[8.93, 0.04]}}

Since I have more data points uptil 10.05, I want to amplify that data more, so in principle I want that part of the plot to take majority of the space and the rest of 4-5 points less space. In a ratio of 3/4, to 1/4 or so. However I am failing to do so. I am currently combining two plots manually by playing around with aspect ratios and such but that is not an elegant approach. Any help will be appreciated.

Also this is just a sample set, I generally have 5-6 plots of such nature in a single plot and therefore benefit from having the y axis in a Log as the y values change drastically.

$\endgroup$
5
  • 1
    $\begingroup$ If you simply want custom x-axis scaling together with a log y-axis, is there a reason you're not using ListPlot with ScalingFunctions->{xScaling, "Log"}? You might also be interested in this question in regards to combining two plots together. $\endgroup$
    – Lukas Lang
    Jan 22 at 20:02
  • $\begingroup$ Presumably you want the x-axis in log rather than the y-axis. ListPlot[data, ScalingFunctions -> {"Log", None}] $\endgroup$
    – Bob Hanlon
    Jan 22 at 20:12
  • $\begingroup$ @LukasLang Thank you for the suggestion, I think that should do it! Sorry for some reason that did not occur to me. $\endgroup$
    – WaleeK
    Jan 23 at 10:07
  • $\begingroup$ @BobHanlon, no I need the data in y in log as generally the graph is used to compare data sets and the differences are more evident and easier to illustrate in a log plot than in a linear plot and the region of interest is 0-10 on x axis and the rest is when the data from both data sets is more or less converges to the same value. However as I said, what Lukas suggested should work $\endgroup$
    – WaleeK
    Jan 23 at 10:10
  • $\begingroup$ There are certain issues when I try to do it with Log as a scaling function or use ListLog Plot. Because as the question stated ListLogPlot does allow scaling as log. The issues now is that when I use scaling as Log in Y and scale and inverse scale in x, I can't seem to get the frameticks for entries greater than 10. And if I join the plots using your row technique than I have to manually adjust the values on the frame, which again consumes a lot fo time as I have a lot of similar graphs to go over $\endgroup$
    – WaleeK
    Jan 24 at 11:29

1 Answer 1

7
$\begingroup$

It is actually pretty easy if you know exactly what properties of graphics you need to prioritize. Options are pretty flexible. A few approaches.

APPROACH 1: arbitrary smooth X-scaling

People were advising X-scaling with "Log". But that, while often fine, is pretty limited. You can define arbitrary X-scaling with functions. For example below is power-scaling:

scaleX[a_][x_]:=x^a

Manipulate[
    ListPlot[data,
    Frame->True,GridLines->{Range[1,45,5],All},FrameTicks->{Range[1,45,5],All},
    ScalingFunctions->{{scaleX[a],Quiet@InverseFunction[scaleX[a]]},None}],
{{a,1},.1,2}]

enter image description here

APPROACH 2: arbitrary Piecewise X-scaling

You can even do this with Piecewise function which basically solves your problem in a pretty neat all-in-single plot way:

simpleX[x_]:=Piecewise[{{3x/4,x<=10.5},{1x/4+10.5/2,x>10.5}}]

ListPlot[data,
    Frame->True,GridLines->{Range[1,45,5],All},FrameTicks->{Range[1,45,5],All},
    ScalingFunctions->{{simpleX,InverseFunction[simpleX]},None}]

enter image description here

APPROACH 3: horizontal plot stacking

enter image description here

Here is an approach that can be packed into a function that takes multiple plots if you understand the mechanics of it. Using your data

data={{0.05,Around[1.2,0.01]},{2.05,Around[1.56,0.01]},{4.05,Around[2.8974,0.0237]},{5.05,Around[3.51,0.02]},{6.05,Around[3.98,0.02]},{8.05,Around[4.3068,0.0287]},{10.05,Around[4.42,0.02]},{15.05,Around[4.81,0.0303]},{25.05,Around[5.34,0.01]},{35.05,Around[6.486,0.035]},{45.05,Around[8.93,0.04]}};

Define split in data:

split=10.5;

Understand which properties are the SAME:

same={GridLines->All,ImageSize->{Automatic,300},BaseStyle->12};

and which and how they are DIFFERENT:

diff1={PlotRange->{{0,split},{0,10}},ImagePadding->16{{1,0},{1,1}},Frame->{{True,False},{True,True}},AspectRatio->1/GoldenRatio,FrameTicks->{Range[10],Automatic}};
diff2={PlotRange->{{split,47},{0,10}},ImagePadding->16{{0,1},{1,1}},Frame->{{False,True},{True,True}},AspectRatio->3 1/GoldenRatio,FrameTicks->All};

Then build in a manner that can be easily generalized:

Row[{
    ListPlot[Select[data,#[[1]]<=split&],same~Join~diff1],
    ListPlot[Select[data,#[[1]]>split&],same~Join~diff2]
}]
$\endgroup$
2
  • $\begingroup$ Thank you for the detailed answer! Combining it with the suggestion from Lukas about using Log as a scaling function for y I think it should do it $\endgroup$
    – WaleeK
    Jan 23 at 10:03
  • $\begingroup$ There are certain issues when I try to do it with Log as a scaling function or use ListLog Plot. Because as the question stated ListLogPlot does allow scaling as log. The issues now is that when I use sclaing as Log in Y and scale and inverse scale in x, I can't seem to get the frameticks for entries greater than 10. And if I join the plots using your row technique than I have to manually adjust the values on the frame, which again consumes a lot fo time as I have a lot of similar graphs to go over $\endgroup$
    – WaleeK
    Jan 24 at 9:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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