20

Is it possible to position ticklabels on negative $y$ axis on its right side? Ticklabels on positive $y$ axis should remain as usual:

enter image description here

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
Bhaskar Dey
  • 381
  • 2
  • 6

3 Answers3

16

Here's one idea. Notice that the tick-marks are flipped as well.

p = Plot[Round[x], {x, -5, 5}, Exclusions -> None, PlotStyle -> Thick];

ticks = Ticks /. AbsoluteOptions[p];

{yticks, labels} =
   Replace[
     ticks[[2]],
     {a_?Negative, b_, c_, x__} :> {a, Sow@Text[b, {0.3, a}];, -c, x},
     1
   ] // Reap;

Show[p, Graphics[labels], Ticks -> {ticks[[1]], yticks}]

Mathematica graphics

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • What about the x axis? – Ajasja Jun 04 '12 at 11:43
  • +1 Nice idea! Why do + and - minor $y$-ticks have different lengths? And why does the $y$-tick at +3.5 seem longer than the one at +3.0? Are these rasterization artefacts? – István Zachar Jun 04 '12 at 11:53
  • @István thanks. I believe it is a rasterization artifact as it appears even at large sizes. – Mr.Wizard Jun 04 '12 at 12:01
  • @Ajasja the OP asked for the y axis modification. You could do the same thing for only x (ticks[[2]] -> ticks[[1]] & {0.3, a} -> {a, 0.3}) or for both in two steps. – Mr.Wizard Jun 04 '12 at 12:29
  • Ahh, sorry, sloppy reading, I was just looking at the example image. +1. – Ajasja Jun 04 '12 at 12:33
10

Lots of magic numbers, no real scalability and rather specific solution for the given case, but it shows how you can build your own tick function easily from scratch. Since I don't think there is any way to finetune the Axes/AxesStyle/Frame options to suit your needs, this is the best I could suggest at the moment. Or you might want to use David Park's Presentations` package or the CustomTicks` package by Mark Caprio to specify aesthetic tick positions for any range (thanks Szabolcs).

{minX, maxX} = {minY, maxY} = {-5, 5}; (* range *)
{xO, yO} = {0, 0}; (* origo *)
d = .2; (* tick length *)
step = 1; (* tick step *)
offset = 1.5; (* tick label offset *)

Plot[IntegerPart@x, {x, minX, maxX}, Exclusions -> None, 
 PlotStyle -> {Black, Thick}, AspectRatio -> 1, 
 PlotRange -> {{minX, maxX}, {minY, maxY}}, Axes -> False, 
 Epilog -> {
   Black, Line[{{minX, yO}, {maxX, yO}}], Line[{{xO, minY}, {xO, maxY}}],
   Table[{
     Line@{{i, yO}, {i, yO + d}},
     Text[i, {i, yO + d}, {0, -offset}]
     }, {i, minX, xO - 1, step}],(* -x *)
   Table[{
     Line@{{i, yO}, {i, yO - d}},
     Text[i, {i, yO - d}, {0, offset}]
     }, {i, xO + 1, maxX, step}],(* +x *)
   Table[{
     Line@{{xO, i}, {xO + d, i}},
     Text[i, {xO + d, i}, {-offset, 0}]
     }, {i, minY, yO - 1, step}],(* -y *)
   Table[{
     Line@{{xO, i}, {xO - d, i}},
     Text[i, {xO - d, i}, {offset, 0}]
     }, {i, yO + 1, maxY, step}] (* +y *)
   }, PlotRangePadding -> Scaled@.05]

Mathematica graphics

István Zachar
  • 47,032
  • 20
  • 143
  • 291
  • You could use the CustomTicks package to generate tick positions, it'd make the solution a little easier to modify/reuse. – Szabolcs Jun 04 '12 at 10:47
  • @Szabolcs: I never used that package, but it seems very useful. Actually, I think it worths its own answer, and would be a perfect starting point for people willing to learn how to use it! So if you have any knowledge, please post your CustomTicks-based solution! – István Zachar Jun 04 '12 at 10:55
  • @Szabolcs I agree, your suggestion would make a good answer on it's own. – Ajasja Jun 04 '12 at 11:43
7

This needs some tweaking, but could be a starting point for a more general solution. The idea is to plot the bottom left quadrant of the plot with a Frame top and right, and the top right quadrant of the plot with a Frame bottom and left. Then Inset those into the complete plot.

bottomleft=Plot[Sin[x],{x,-4,4},Frame->{False,False,True,True}, 
  FrameTicks->All,PlotRange->{{Automatic,0},{Automatic,0}}];
topright=Plot[Sin[x],{x,-4,4},Frame->{True,True,False,False},
  FrameTicks->All,PlotRange->{{0,Automatic},{0,Automatic}}];

Plot[Sin[x],{x,-4,4},Ticks->False,
  Epilog->{Inset[bottomleft,{0,0},{0,0},Scaled[0.58]],Inset[topright,{0,0},{0,0},Scaled[0.58]]}]

enter image description here

Clearly there is a problem with all the ticks at the origin, and the insets had to be scaled by trial and error, but there might be a way to automate that.

Verbeia
  • 34,233
  • 9
  • 109
  • 224
Simon Woods
  • 84,945
  • 8
  • 175
  • 324