Skip to main content

plotting - Display frame-tick labels on top side


I am making a standard framed Plot and would like the frame tick labels for the horizontal axis to appear on the top frame edge.



I know I can do this by hand using, for example:


Plot[x, 
{x, 0, 5},
Frame -> True,
FrameTicks -> {{Automatic,
Automatic}, {{{0, ""}, {1, ""}, {2, ""}, {3, ""}, {4, ""}, {5,
""}}, {0, 1, 2, 3, 4, 5}}}
]

But that is so terribly cumbersome, how can I just make the standard/default frame ticks appear on the top instead of the bottom?




Answer



It's a hack, but this should work:


Plot[x, {x, 0, 5}, Frame -> True, 
FrameTicks -> {{Automatic, Automatic}, {Automatic, All}},
ImagePadding -> {{20, 20}, {4, 20}}]

imagemargins


The values for ImagePadding are chosen so as to leave no room for the bottom tick labels to be displayed. You can change the margins from 20 to 40 (e.g.) if you need more room to display additional labels. The bottom image margin of 4 is the one that cuts off the undesired labels.


Edit: a more systematic approach


The following approach is based on a different idea that will not require any devious cropping of unwanted text. At the same time, it still avoids the need to specify tick marks manually.



To achieve this, I use FindDivisions to emulate the Automatic tick placement (I didn't try to get it exactly right, but added some customizability). The ticks are calculated automatically for each plot, and there are versions with and without tick labels: tickFunction and tickFunctionNoLabel. To avoid having to think about these functions every time you make a plot, I just use SetOptions to make Plot call them automatically:


Clear[tickFunction, tickFunctionNoLabel, gridFunction, divisionFunction]

divisionFunction[xMin_, xMax_] :=
FindDivisions[{xMin, xMax}, {8, 5}];

gridFunction[xMin_, xMax_] := First[divisionFunction[xMin, xMax]]

Options[tickFunction] = {"MinorLength" -> 0.005, "MajorLength" -> .01,
"InsideOutside" -> {1, 0}};


tickFunction[xMin_, xMax_, OptionsPattern[]] :=
Module[{major, minor},
{major, minor} = divisionFunction[xMin, xMax];
Join[Map[{#, #,
OptionValue["InsideOutside"] OptionValue["MajorLength"]} &,
major], Map[{#, "",
OptionValue["InsideOutside"] OptionValue["MinorLength"]} &,
Flatten[minor[[All, 2 ;; -2]]]]]
]


tickFunctionNoLabel[xMin_, xMax_] :=
Map[{#[[1]], "", #[[-1]]} &, tickFunction[xMin, xMax]]

SetOptions[Plot,
FrameTicks ->
{{tickFunction, tickFunctionNoLabel}, {tickFunctionNoLabel, tickFunction}}];

Plot[x, {x, 0, 5}, Frame -> True]


tickfunction


As you see, I didn't have to add any options to this Plot command, and the frame ticks come out properly.


I added the ability to adjust the lengths of the major and minor ticks as options of the tickFunction. Another option is called "InsideOutside" which decides how much of the ticks is inside or outside of the frame. By default, it's all inside, specified by an option value {1,0}. Here is what it looks like with external ticks:


SetOptions[tickFunction, "InsideOutside" -> {0, 1}];

Plot[x, {x, 0, 5}, Frame -> True,
GridLines -> gridFunction]

grid


For fun, I added a grid to this plot (that's when you really need external ticks, I think). The grid is derived from the same FindDivisions that underlies the ticks, as calculated in divisionFunction.



In this approach, the placement of the labels is entirely controlled by the order in which you call tickFunction or tickFunctionNoLabel in the FrameTicks option specification.


For example, you can do the following:


SetOptions[Plot, 
FrameTicks -> {{tickFunctionNoLabel,
tickFunction}, {tickFunctionNoLabel, tickFunction}}];

Plot[x, {x, 0, 5}, Frame -> True]

right label


Finally, an example for different tick lengths, where I also choose to specify the tick functions directly as an option in Plot:



SetOptions[tickFunction, "InsideOutside" -> {1, 0}, 
"MajorLength" -> .02, "MinorLength" -> .01];

Plot[x, {x, 0, 5}, Frame -> True,
FrameTicks -> {{tickFunction, tickFunction}, {tickFunctionNoLabel,
tickFunction}}]

tick lengths


To further customize the automatic tick marks, you can also change the parameters of FindDivisions in the definition of divisionFunction.


Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

equation solving - Invert and fit implicitly defined curve

I need to fit an implicitly defined curve. I thought I could get some data out of Solve , and then using FindFit . Therefore, I would like to find the relation the parametric curve defined by $F(x,y)=0$: Solve[-(1/2) + 1/2 (0.41202 BesselK[0, 0.1 Sqrt[x^2 + y^2]] + (0.101483 x BesselK[1, 0.1 Sqrt[x^2 + y^2]])/Sqrt[x^2 + y^2]) == 0, y] But I can't get an output: Solve was unable to solve the system with inexact coefficients or the system obtained by direct rationalization of inexact numbers present in the system. Since many of the methods used by Solve require exact input, providing Solve with an exact version of the system may help. >> Edit: In particular, I would like to fit the data coming from the curve with the expression of another curve, and not with a function $f(x)$. In particular, since this clearly looks like a cardioid , I would like it to fit to something like it. What other strategies could I try?

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...