3
$\begingroup$

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?

$\endgroup$
  • 3
    $\begingroup$ Unfortunately, graphics in Mathematica is just terribly cumbersome. You'll have to get used to it. You can use FrameTicks -> {{Automatic, Automatic}, {None, All}}, perhaps. Or use Automatic instead of None and just delete the labels in a drawing program. (That's what I've done before.) Biggest problem is that it does not seem to be possible to retrieve the automatic tick specification (especially the tick lengths) in order to reproduce it. $\endgroup$ – Oleksandr R. Jul 24 '15 at 0:29
  • $\begingroup$ OK thanks, I guess 'All' will do for now. $\endgroup$ – Jay Jul 24 '15 at 0:43
5
$\begingroup$

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.

$\endgroup$
  • 1
    $\begingroup$ (+1) Mathematica has surprisingly many Tick-related bugs! :( $\endgroup$ – Alexey Popkov Jul 24 '15 at 3:58
  • $\begingroup$ Thanks for the comprehensive answer! I wasn't expecting it to be so much trouble.. $\endgroup$ – Jay Jul 28 '15 at 4:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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