17
$\begingroup$

I managed to turn the ticks inside-out but the ticks go now through the numbers. In fact I would like to have it like in the picture attached (ticks pointing outside the plot and no additional ticks between the numbers). Has anyone a suggestion?

data={-1.2056,-(7288960271654/4985881289361),-1.30053,-(33199059446612625/13128459048331036),-(5130109517723890585/5148852459134416857),-1.73904,-1.164,-1.83398,-0.97505,-(152151059187768664247/302333262014074402254),-(33596749386427335752225/52657796909983176600514),-0.785963,-0.398132,-(2414923435622638997136189344226575/3392598745831412249336953513454508),-0.820439};
a=First[HistogramList[data]]
b=Range[Max[Last[HistogramList[data]]]]
Histogram[
  data,
  BarOrigin->Left,
  Axes->False,
  Frame->{{True,None},{True,None}},
  FrameTicks->{
              {Transpose[{a,a,Table[{-0.02,0},{i,Length[a]}]}],None},
              {Transpose[{b,b,Table[{-0.02,0},{i,b}]}],None}
              }
]

Example

$\endgroup$
3
  • 2
    $\begingroup$ In future, please avoid the use of %n in the code you post here. A good number of folks use a $HistoryLength different from the default and you can't guarantee %%% works for all :) $\endgroup$
    – rm -rf
    Mar 14, 2012 at 19:47
  • $\begingroup$ @R.M out of curiosity, why do you change $HistoryLength and what does it do? (Or am I opening a big can of worms, and should actually post the question :)?) $\endgroup$
    – tkott
    Mar 14, 2012 at 20:00
  • 1
    $\begingroup$ @tkott it changes the number of saved output expression that Mathematica keeps. When working with large expressions setting $HistoryLength = 0 can save a lot of memory. I personally use 3. $\endgroup$
    – Mr.Wizard
    Mar 14, 2012 at 20:10

5 Answers 5

10
$\begingroup$

This works, but it does require some manual tweaking

Histogram[data, BarOrigin -> Left, Axes -> False, 
 Frame -> {{True, None}, {True, None}}, 
 FrameTicks -> {{Transpose[{a, 
      Row[{#, Pane["", {10, Automatic}]}] & /@ a, 
      Table[{-0.02, 0}, {i, Length[a]}]}], 
    None}, {Transpose[{b, 
      Pane[#, {Automatic, 20}, Alignment -> {Center, Bottom}] & /@ b, 
      Table[{-0.02, 0}, {i, b}]}], None}}]

Mathematica graphics

$\endgroup$
2
  • $\begingroup$ huh, and I thought the way I answered was hacky. If @Heike does it similarly, then I guess I'm doing OK $\endgroup$
    – tkott
    Mar 14, 2012 at 19:58
  • $\begingroup$ @tkott you are definitely doing OK. You have given some nice answers recently. $\endgroup$
    – Verbeia
    Mar 14, 2012 at 21:31
8
$\begingroup$

Edit 3

Looking at the other solutions, I noticed that they all have more or less cumbersome ways of addressing the spacing problem of the labels. I think this particular aspect is more robustly addressed using Framed as I did in the original solution below (where I focused on using LevelScheme). Here is what a bare-bones solution without additional packages would look like:

Histogram[data, BarOrigin -> Left, Axes -> False, 
 Frame -> {{True, None}, {True, None}}, FrameTicks -> Map[
   {Transpose[{#, 
       Framed[#, FrameStyle -> None, 
          FrameMargins -> 10] & /@ #, {-0.02, 0} & /@ #}], 
     None} &, {a, b}]]

LevelScheme based solution:

If you do this kind of thing often, it may be worth starting over and doing your plots with the CustomTicks package by Mark Caprio. The web page has the package as a zip file (the main package is called LevelScheme). There is a separate user guide for CustomTicks near the bottom of that page. For example, there is an option called ShowMinorTicks that can be set to False. You can still use "in" and "out" lengths for the tick marks to get them to point out of the frame as in your example.

Edit

Here is a version of the original histogram code using CustomTicks:

Histogram[data, BarOrigin -> Left, Axes -> False, 
 Frame -> {{True, None}, {True, None}}, 
 FrameTicks -> {
  {LinTicks[-3, 0, 1, 1, MajorTickLength -> {0, .02}], 
    None}, 
  {LinTicks[0, 8, ShowMinorTicks -> False, 
    MajorTickLength -> {0, .02}, 
     TickLabelFunction -> (Framed[#2, FrameStyle -> None] &)], 
    None}
 }]

In the extremely useful convenience function TickLabelFunction provided by the package, I used Framed without frame to create more space for the labels. The output looks like this:

histogram with CustomTicks

A final word about installing the package on Mac OS X: you have to follow the instructions in the LevelScheme guide, and avoid installing into the standard location /Library/Mathematica/Applications/! This is a little weird, but if you install into any other directory (e.g., in your home directory), the package should load fine. I remember this having been that way for years, but it's just a minor hiccup in an otherwise very useful package.

Edit 2 Updated

If you simply drag the LevelScheme folder into Mathematica's Applications folder on Mac OS X, the package will not be loadable (as of version 3.52). You'll get the error

Get::noopen: Cannot open LevelScheme`. >>

A more streamlined installation process on Mac OS X requires modifying the init.m file in the downloaded distribution. Instead of describing this in words, I've written an "installer" function that should be able to set up LevelScheme for you (only for Mac OS X):

installLevelScheme[downloadDirectory_] := 
 Module[{initPath, initContents,
   initFile = FileNameJoin[{"LevelScheme", "init.m"}], 
   targetDir = 
    FileNameJoin[{$UserBaseDirectory, "Applications", "LevelScheme"}]},
  initPath = FileNameJoin[{targetDir, "Kernel"}];
  Check[SetDirectory[downloadDirectory];
   initContents = Import[initFile, "Text"];
   Print[initContents];
   DeleteFile[initFile], 
   Return["Unzip the downloaded file (again) and enter the name of the resulting folder!"]];
  Check[CopyDirectory[
    FileNameJoin[{downloadDirectory, "LevelScheme"}], targetDir], 
   Return["Installation directory already exists and hasn't been modified"]];
  Check[CreateDirectory[initPath], 
   Return["Initialization directory already exists and hasn't been modified"]];
  Export[FileNameJoin[{initPath, "init.m"}], 
   "AppendTo[$Path,\"/Library/Mathematica/Applications/LevelScheme\"];\n" <> 
    initContents, "Text"];]

Now all you have to do is download LevelScheme from the web page linked above and unzip it to find a folder called ~/Downloads/LevelScheme (in my case). Make sure that the directory /Library/Mathematica/Applications/LevelScheme doesn't exist yet, and then call the above function like this:

installLevelScheme["~/Downloads/LevelScheme"]

Now you should restart Mathematica. To load the package, it is from now on sufficient to just type the standard command

Needs["LevelScheme`"]
$\endgroup$
11
  • $\begingroup$ I followed the instructions, still I have troubles to install LevelScheme: AppendTo[$Path, "/Users/me/Documents/MyPaper/Mathematica/LevelScheme"]; Get["LevelScheme"]` The output was $Failed. What I am doing wrong? $\endgroup$
    – John
    Mar 25, 2012 at 11:43
  • $\begingroup$ @John To verify that you're pointing to the right place, check that SetDirectory["/Users/me/Documents/MyPaper/Mathematica/LevelScheme"];FileNames[] yields the output {"BlockOptions", "ClipToRectangle", "CustomTicks", "doc", "ForEach", "InheritOptions", "LevelScheme", "NamedColors"}. If not, you may be too deep or too shallow in the folder hierarchy of the package. Let me know what you see. $\endgroup$
    – Jens
    Mar 25, 2012 at 16:03
  • $\begingroup$ It's really annoying when package authors use nonstandard installation/load schemes such as with $LevelScheme$. You $can$ put the directory in /Library/Mathematica/Applications or in your user base directory: inside LevelScheme make subdirectory Kernel then put there file init.m from LevelScheme/LevelScheme/ and edit the file by inserting the appropriate AppendTo[$Path,...]; expression. $\endgroup$
    – murray
    Mar 25, 2012 at 16:12
  • $\begingroup$ It's also awkward that $LevelScheme$ uses some .pdfs and some example notebooks for documentation rather than the current Documentation Center paradigm. But we should still be thankful for the application's author making this available at all. $\endgroup$
    – murray
    Mar 25, 2012 at 16:16
  • $\begingroup$ @murray Thanks for these observations! The init.m modification you suggested does indeed work, and streamlines the loading process a lot. I'll try to think of a way to add these instructions to my answer. $\endgroup$
    – Jens
    Mar 25, 2012 at 17:05
4
$\begingroup$

Here is a variant of Heike's answer using AdjustmentBox. The DisplayForm element is essential for it to show properly.

Histogram[data, BarOrigin -> Left, Axes -> False, 
 Frame -> {{True, None}, {True, None}}, 
 FrameTicks -> {{Transpose[{a, DisplayForm@AdjustmentBox[#, 
                   BoxBaselineShift -> 0, 
          BoxMargins -> {{0, 1}, {0, 0}}] & /@ a, 
      Table[{-0.02, 0}, {i, Length[a]}]}], 
    None}, {Transpose[{b, DisplayForm@AdjustmentBox[#, 
                   BoxBaselineShift -> 0, 
          BoxMargins -> {{0, 1}, {0, 0}}] & /@ b, 
      Table[{-0.02, 0}, {i, b}]}], None}}]

The AdjustmentBox approach is a bit more flexible if you want to move the labels with a lot of control, as shown in this example with the x-axis labels tucked up next to the FrameTicks.

enter image description here

$\endgroup$
3
$\begingroup$

Here's a really (really) hacky way of doing this, and I hope someone has come up with a better answer while I was looking at this.

Histogram[data, BarOrigin -> Left, Axes -> False, 
 Frame -> {{True, None}, {True, None}}, 
 FrameTicks -> {{Transpose[{a, 
      StringJoin[#, "   "] & /@ (ToString /@ a), 
      Table[{-0.02, 0}, {i, Length[a]}]}], 
    None}, {Transpose[{b, StringJoin["\r", #] & /@ (ToString /@ b), 
      Table[{-0.02, 0}, {i, b}]}], None}}]

Resulting in

Mathematica graphics

$\endgroup$
2
$\begingroup$

Another hack: Use the Style option to create an invisible tickmark that extends in both sides of the axis and prepend the tick list with it. You can control the placement of the labels playing with the two parameters of the invisible tick.

Using data, a and b defined in OP's question,

 Histogram[data, BarOrigin -> Left, Axes -> False,  
 Frame -> {{True, True}, {True,   True}}, 
 FrameTicks -> {{Prepend[
 Transpose[{a, a, Table[{-0.02, 0}, {i, Length[a]}]}], 
 {a[[1]], "", {-0.02, .02}, Opacity[0]}], 
 Prepend[Transpose[{a, a, Table[{-0.02, 0}, {i, Length[a]}]}], 
 {a[[1]], "", {-0.05, .05}, Opacity[0]}]}, 
 {Prepend[Transpose[{b, b, Table[{-0.02, 0}, {i, b}]}], 
 {b[[1]], "", {-0.02, .04}, Opacity[0]}], 
  Prepend[Transpose[{b, b, Table[{-0.02, 0}, {i, b}]}], 
 {b[[1]], "", {-0.02, .1}, Opacity[0]}]}}]

gives

frameticks outside

$\endgroup$

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.