17

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

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
John
  • 4,361
  • 1
  • 26
  • 41
  • 2
    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 :) – rm -rf Mar 14 '12 at 19:47
  • @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 :)?) – tkott Mar 14 '12 at 20:00
  • 1
    @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. – Mr.Wizard Mar 14 '12 at 20:10

5 Answers5

10

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

Heike
  • 35,858
  • 3
  • 108
  • 157
8

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`"]
Jens
  • 97,245
  • 7
  • 213
  • 499
  • 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?

    – John Mar 25 '12 at 11:43
  • @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. – Jens Mar 25 '12 at 16:03
  • 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. – murray Mar 25 '12 at 16:12
  • 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. – murray Mar 25 '12 at 16:16
  • @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. – Jens Mar 25 '12 at 17:05
  • @Jens: There are a whole bunch of add-ons out there that have similar problems -- often just a .m package and a doc file, perhaps a .nb and perhaps a source .nb notebook. Merely in order to streamline the top-level Appplications folder of my $UserBaseDirectory, I now always use the Kernel/init.m maneuver. – murray Mar 25 '12 at 19:39
  • @Jens: re your edit, about to your answer: ooh! With a function to modify the way this one particular application is installed, on one platform, what should come next is obviously a package for installing any non-standard-install package and on any platform. – murray Mar 26 '12 at 00:20
  • @murray And what about an installer for that package? – Jens Mar 26 '12 at 00:26
  • I have it installed in Applications and it seems to work fine. I'm on Windows though. What goes wrong if you install into Applications? – Szabolcs Jul 16 '12 at 17:32
  • @Szabolcs I just checked by removing the init.m file created in this answer, and edited the post to include the error message I got. Hopefully that will help people find this fix if they search for the error. So Applications works on Windows, but on Mac it only works with the fix @murray gave above. – Jens Jul 16 '12 at 18:02
  • I wish I'd seen this earlier... I just installed the package and went through all the init.ms and (manually) added an extra LevelScheme\``. Could you consider posting this as an answer to [this question](http://mathematica.stackexchange.com/questions/28268/cant-load-levelscheme-package). For the record, copy-pasting the subfolders directly to the "Applications" folder also works without the need to place LevelScheme'sinit.m` inside a "Kernel" folder – gpap Jan 16 '14 at 11:41
4

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

Verbeia
  • 34,233
  • 9
  • 109
  • 224
3

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

tkott
  • 4,939
  • 25
  • 44
2

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

kglr
  • 394,356
  • 18
  • 477
  • 896