12
$\begingroup$

I'm working on making some BarCharts, however, some of my data is contained within a small range so I want the plot to start above 0 and cut-off the bars below that, however, when I try to use PlotRange the bars are not cropped properly (they extend below the axis) and if you try to introduce ChartLabels they are cut in half!

BarChart[RandomReal[1, 10], BarSpacing -> Large, ChartLabels -> Range[10]]

Mathematica graphics

BarChart[RandomReal[1, 10], BarSpacing -> Large, PlotRange -> {Automatic, {0.2, 1}}]

Mathematica graphics

BarChart[RandomReal[1, 10], BarSpacing -> Large, PlotRange -> {Automatic, {0.2, 1}}, ChartLabels -> Range[10]]

Mathematica graphics

I've tried playing around with ImagePadding and BarOrigin but nothing seems to work. Is there a better solution?

With a ListPlot adjusting the PlotRange

ListPlot[RandomReal[1, 10], PlotRange -> {Automatic, {0.2, 1}}]

Mathematica graphics

$\endgroup$
7
  • 3
    $\begingroup$ I don't want to be rude, but forcing the vertical axis to start at anything other than zero is misleading. See chapter 5 of "How to Lie with Statistics". $\endgroup$ Feb 20, 2013 at 18:43
  • 2
    $\begingroup$ I am not near a Mathematica installation so I can't check, but isn't this fixed using PlotRangeClipping -> True? $\endgroup$
    – Verbeia
    Feb 20, 2013 at 19:08
  • 1
    $\begingroup$ @GustavoDelfino I would have to disagree. How is this different than background subtraction. There could be a constant baseline for all the measurements even where one is an "end point". $\endgroup$
    – s0rce
    Feb 20, 2013 at 23:24
  • 1
    $\begingroup$ s0rce, I saw your (deleted) comment that my method wasn't working, and then the Accept (thanks). I assume that you had to make some changes to the code to get it to work in your version of Mathematica. Could you tell me what those were, or add them to my answer so that it is more complete? $\endgroup$
    – Mr.Wizard
    Feb 24, 2013 at 6:17
  • $\begingroup$ By the way, I have no idea why this question has only one vote. I thought it was quite a good question myself! $\endgroup$
    – Mr.Wizard
    Feb 24, 2013 at 6:18

3 Answers 3

8
$\begingroup$

Good question. The problem is that the chart labels are placed as Text objects inside the Graphics body rather than as Ticks along an axis or frame. Further, the extent of the bars is not limited by the PlotRange. To get around this we can convert the Text labels to Ticks. (Version 7 does not appear to accept Placed[. . . , Axis] as shown in kguler's answer or this could likely be simplified.)

Since the format of the output of BarChart likely changes between version I shall describe what I am doing so that it can be adapted to other versions.

First I create a chart with additional options to yield the look desired:

ch =
 BarChart[RandomReal[1, 10],
  BarSpacing -> Large,
  PlotRange -> {Automatic, {0.2, 1}},
  PlotRangePadding -> {Automatic, 0},
  PlotRangeClipping -> True,
  ChartLabels -> Range@10
 ]

Mathematica graphics

No labels are visible but they are present in the code itself. There is a GraphicsGroup containing a series of Text objects of the form:

Text[Pane[1], Offset[{0, -2}, {0.5, 0}], ImageScaled[{1/2, 1}]]

From these we can extract the label information:

labels = Cases[ch[[1]], Text[lbl_, Offset[_, {pos_, _}], ___] :> {pos, lbl, 0}, -4];

And then add them to the chart as tick labels:

Show[ch, Ticks -> {labels, Automatic}]

Mathematica graphics


Update

In recent versions of Mathematica BarChart defaults to Axes -> {False, True}; the x axis must be drawn for the Tick labels to be displayed:

Show[ch, Ticks -> {labels}, Axes -> True]

enter image description here

Alternatively Frame and FrameTicks may be used as s0rce shows below.


edit (by s0rce):

I'm not sure why, but this wasn't working for me as is. However, I almost always use Frame->True and when I did that everything worked (with some minor FrameTicks and PlotRangePadding adjustment).

ch = 
 BarChart[RandomReal[1, 10], 
  BarSpacing -> Large, 
  Frame -> True, 
  PlotRange -> {Automatic, {0.2, 1}}, 
  PlotRangePadding -> {Automatic, 0}, 
  PlotRangeClipping -> True, 
  ChartLabels -> Range@10
]

labels = Cases[ch[[1]], 
   Text[lbl_, Offset[_, {pos_, _}], ___] :> {pos, lbl, 0}, -4];

Show[ch, FrameTicks -> {labels, Automatic, False, False}]

Mathematica graphics

$\endgroup$
2
  • 1
    $\begingroup$ There is an extra comma after Range@10 in the last code blocl. $\endgroup$
    – Art
    Apr 14, 2016 at 15:54
  • $\begingroup$ @Art Thanks, I'll fix that now. $\endgroup$
    – Mr.Wizard
    Apr 14, 2016 at 21:07
3
$\begingroup$

Ok, you mean like this? Will clean this more, just wanted to know if this is what you wanted. If you do not want to move the origin also, you can remove the AxesOrigin -> {0, z} from the code

Manipulate[

 f[{{xmin_, xmax_}, {ymin_, ymax_}}, ___] := 
  Module[{h = ymax - ymin, t},
   t = If[z >= h, h, z];
   Polygon[{{xmin, ymin + t}, {xmax, ymin + t}, {xmax, ymax}, {xmin, ymax}}]];

 Grid[{
   {
    BarChart[data, BarSpacing -> Large, ImageSize -> 300, 
     ChartElementFunction -> f, PlotRange -> {All, {-5, 5}},AxesOrigin -> {0, z}],

    BarChart[data, BarSpacing -> Large, ImageSize -> 300, 
     PlotRange -> {All, {-5, 5}}, ChartLabels -> Placed[Range[10], Below], 
     AxesOrigin -> {0, 0}]
    }}],

 {{z, 0.2, "z="}, 0, 3, .1, Appearance -> "Labeled"},

 TrackedSymbols :> {z},
 Initialization :>
  {
   data = RandomReal[{1, 5}, 10];
   }
 ]

Mathematica graphics

$\endgroup$
1
  • $\begingroup$ I want to chop off the bars at an arbitrary y-value, in this case 0.2 and then move the x-axis up to that point and cut off the bars below. Basically change the y PlotRange. $\endgroup$
    – s0rce
    Feb 20, 2013 at 18:40
2
$\begingroup$
modifyF = With[{pl = PlotRange@#}, # /. RectangleBox[{xmin_, 0.}, {xmax_, ymax_}, z___] :> 
  RectangleBox[{xmin, pl[[2, 1]]}, {xmax, Min[pl[[2, 2]], Max[pl[[2, 1]], ymax]]}, z]]&;

Example:

bc = BarChart[RandomReal[1, 10], BarSpacing -> Large, ImagePadding -> 20,
   ChartLabels -> Placed[Range[10], Axis], PlotRange -> {.2, 1}, ImageSize -> 400];

Row[{bc, modifyF@bc}]

enter image description here

$\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.