Skip to main content

plotting - How to set the ratio between the vertical and horizontal scales of plots?



The documentation says that when AspectRatio->Automatic is specified, Mathematica



determines the ratio of height to width from the actual coordinate values in the plot.



When doing this, Mathematica treats the units in the vertical and horizontal axes as having the same length on the screen.


This is reasonable when the units for both axes are the same (e.g., light-years), but not necessarily so when the units for the two axes are incommensurable (e.g. luminosity vs. seconds of arc), or when the extents in the two dimensions are vastly different (which, with AspectRatio->Automatic, would correspond to an effective aspect ratio close to 0 or infinity).


For such situations I would like a convenient way to set the aspect ratio equal to r×A, where r is a scaling factor of my choosing, and A is the aspect ratio computed per the usual AspectRatio->Automatic rules.


Does Mathematica offer a way to do this?




In case the description above is not sufficiently clear, here's an example.



First I generate some synthetic data.


data = With[{n = 50},
{
{RandomReal[{-35, -30}, n], RandomInteger[{-20100, -20000}, n]}\[Transpose],
{RandomReal[{0, 5}, n], RandomInteger[{0, 80}, n]}\[Transpose]
}
];

In the horizontal direction, for both datasets the range extends over about 5 units, but in the vertical direction, the ranges extend over ca. 100 and 80 units, respectively. This would correspond to A=20 and A=16, respectively (see above for the definition of A). But let's suppose I want r=0.25 (i.e. I want the vertical units to have only one-quarter of the screen length of the horizontal ones). If so, then the desired aspect ratios for the two datasets would be 5 and 4, respectively.


In any case, here are the plots that get produced with AspectRatio->Automatic, showing the unscaled aspect ratios (A=20 and A=16) just mentioned1:



ListPlot[#, AspectRatio -> Automatic, Frame -> True, 
FrameTicks -> {None, Automatic}] & /@ data

Mathematica graphics


For this example, of course, the calculation of the desired aspect ratio rA was relatively straightforward, since I've concocted datasets having specific values of A. In general, however, I don't want to have to figure out A for every plot.




BTW, in case anyone wonders, specifying r as AspectRatio won't do it:


ListPlot[#, AspectRatio -> 0.25, Frame -> True,
FrameTicks -> {None, Automatic}] & /@ data


Mathematica graphics




1 I show two plots in this example because the main motivation for wanting to control the relative sizes of axis units is to make different plots readily comparable, even when they are not plotted as part of, say, a grid. As it happens, I find the plots shown above unsatisfactory not only because they don't have the desired aspect ratios, but also because their relative sizes are not directly comparable (for this the two plots should have same width, and the one on the right should be 80% as tall as the one on the left). Of course, this second problem is a separate issue altogether, but I mention it here only FWIW, by way of additional background, and to increase the chance that any answer I get for the thread's question is not one that makes solving this second problem unnecessarily difficult.



Answer



Assuming that the original AspectRatio that you want can be obtained from ListPlot[data]:


Manipulate[
ListPlot[#,
AspectRatio -> r (AspectRatio /. AbsoluteOptions[ListPlot[data]]),
Frame -> True, FrameTicks -> {None, Automatic}] & /@
data, {{r, 1}, 0.1, 10}]


result


Comments

Popular posts from this blog

mathematical optimization - Minimizing using indices, error: Part::pkspec1: The expression cannot be used as a part specification

I want to use Minimize where the variables to minimize are indices pointing into an array. Here a MWE that hopefully shows what my problem is. vars = u@# & /@ Range[3]; cons = Flatten@ { Table[(u[j] != #) & /@ vars[[j + 1 ;; -1]], {j, 1, 3 - 1}], 1 vec1 = {1, 2, 3}; vec2 = {1, 2, 3}; Minimize[{Total@((vec1[[#]] - vec2[[u[#]]])^2 & /@ Range[1, 3]), cons}, vars, Integers] The error I get: Part::pkspec1: The expression u[1] cannot be used as a part specification. >> Answer Ok, it seems that one can get around Mathematica trying to evaluate vec2[[u[1]]] too early by using the function Indexed[vec2,u[1]] . The working MWE would then look like the following: vars = u@# & /@ Range[3]; cons = Flatten@{ Table[(u[j] != #) & /@ vars[[j + 1 ;; -1]], {j, 1, 3 - 1}], 1 vec1 = {1, 2, 3}; vec2 = {1, 2, 3}; NMinimize[ {Total@((vec1[[#]] - Indexed[vec2, u[#]])^2 & /@ R...

functions - Get leading series expansion term?

Given a function f[x] , I would like to have a function leadingSeries that returns just the leading term in the series around x=0 . For example: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x)] x and leadingSeries[(1/x + 2 + (1 - 1/x^3)/4)/(4 + x)] -(1/(16 x^3)) Is there such a function in Mathematica? Or maybe one can implement it efficiently? EDIT I finally went with the following implementation, based on Carl Woll 's answer: lds[ex_,x_]:=( (ex/.x->(x+O[x]^2))/.SeriesData[U_,Z_,L_List,Mi_,Ma_,De_]:>SeriesData[U,Z,{L[[1]]},Mi,Mi+1,De]//Quiet//Normal) The advantage is, that this one also properly works with functions whose leading term is a constant: lds[Exp[x],x] 1 Answer Update 1 Updated to eliminate SeriesData and to not return additional terms Perhaps you could use: leadingSeries[expr_, x_] := Normal[expr /. x->(x+O[x]^2) /. a_List :> Take[a, 1]] Then for your examples: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x), x] leadingSeries[Exp[x], x] leadingSeries[(1/x + 2 + (1 - 1/x...

What is and isn't a valid variable specification for Manipulate?

I have an expression whose terms have arguments (representing subscripts), like this: myExpr = A[0] + V[1,T] I would like to put it inside a Manipulate to see its value as I move around the parameters. (The goal is eventually to plot it wrt one of the variables inside.) However, Mathematica complains when I set V[1,T] as a manipulated variable: Manipulate[Evaluate[myExpr], {A[0], 0, 1}, {V[1, T], 0, 1}] (*Manipulate::vsform: Manipulate argument {V[1,T],0,1} does not have the correct form for a variable specification. >> *) As a workaround, if I get rid of the symbol T inside the argument, it works fine: Manipulate[ Evaluate[myExpr /. T -> 15], {A[0], 0, 1}, {V[1, 15], 0, 1}] Why this behavior? Can anyone point me to the documentation that says what counts as a valid variable? And is there a way to get Manpiulate to accept an expression with a symbolic argument as a variable? Investigations I've done so far: I tried using variableQ from this answer , but it says V[1...