3
$\begingroup$

Is there a way to reproduce the following behavior in BarChart?

enter image description here

I have seen this in ListPlot, but I am not sure how it can be modified for a bar chart:

Generating a broken or snipped axis in ListPlot

$\endgroup$
2
$\begingroup$

System`BarFunctionDump`ScaleBreakRectangle

For the looks we can use the undocumented function System`BarFunctionDump`ScaleBreakRectangle as the setting for the option ChartElementFunction:

SeedRandom[777]
BarChart[RandomInteger[1000, {4, 3}], ImageSize -> Large, 
 ChartStyle -> "Rainbow",  ChartLabels -> {Range[4], {"A", "B", "C"}},
 ChartElementFunction ->(System`BarFunctionDump`ScaleBreakRectangle[##, 
     Charting`ChartStyleInformation["ScaleBreaker"] = {300},
      "Frequency" -> 3, "Amplitude" -> 10, "BreakWidth" -> 10] &)]

enter image description here

Change {300} to, say, {150, 300, 600} to get multiple breaks:

enter image description here

We can also combine it with other built-in functions. For example, using

ChartElementFunction -> ({ChartElementData["GlassRectangle"][##], 
     EdgeForm[{AbsoluteThickness[2], White}], FaceForm[], 
     System`BarFunctionDump`ScaleBreakRectangle[##, 
      Charting`ChartStyleInformation["ScaleBreaker"] = {150, 300, 600},
      "Frequency" -> 3, "Amplitude" -> 10, "BreakWidth" -> 10]} &)

we get

enter image description here

NEXT: (1) Using different scales for the upper and lower portions of rectangles, (2) adjusting the vertical ticks accordingly, and (2) modifying the vertical axis to add a snip glyph.

ClearAll[scF, iscF, cEF, snip, inset]
scF[t_, sc_: 1/2] := If[# <= t, #, t + sc (# - t)] &;

iscF[t_, sc_: 1/2] := InverseFunction[scF[t, sc]];

cEF[t_, sc_: 1/2] := System`BarFunctionDump`ScaleBreakRectangle[
  {#[[1]], {#[[2, 1]], scF[t, sc]@#[[2, 2]]}}, #2, 
    Charting`ChartStyleInformation["ScaleBreaker"] = {t}, 
    "Frequency" -> 2, "Amplitude" -> 3., "BreakWidth" -> 2] &;

snip = Graphics[{Antialiasing -> True, EdgeForm[None], FaceForm[White], 
    Polygon[{{-1, -1/6}, {1, 5/6}, {1, 1/6}, {-1, -5/6}}], 
    Black, CapForm["Butt"], AbsoluteThickness[1], 
    Line[{{{-1, -5/6}, {1, 1/6}}, {{-1, -1/6}, {1, 5/6}}}]}];

inset[pos_: ImageScaled[{.2, .1}], size_: Scaled[{.04, .04}]] := 
 Inset[snip, pos, Automatic, size]

Examples:

SeedRandom[1]
data = RandomReal[{0, 300}, 10];

yticks = Join @@ (#[Quiet @ 
 Charting`ScaledTicks[{scF[100], iscF[100]}][##2, {10, 5}]] & @@@ 
  {{Most, 0, 100}, {Rest, 100, Max @ data}});

Row[{BarChart[data, ImageSize -> 500, ChartStyle -> "Rainbow", 
    ChartLabels -> Range[10], AxesOrigin -> {-1/5, 0}, 
    ImagePadding -> Scaled[.03]], 
  BarChart[data, ImageSize -> 500, ChartStyle -> "Rainbow",  
    ChartLabels -> Range[10], AxesOrigin -> {-1/5, 0},
    Ticks -> {Automatic, yticks}, ChartElementFunction -> cEF[100], 
    PlotRangeClipping -> False, ImagePadding -> Scaled[.03], 
    Epilog -> {inset[{-1/5, 100}], 
      Text[100, Offset[{-15, 0}, {-1/5, 100}]]}]}]

enter image description here

Use ChartElementFunction -> cEF[100, 1/4] and change yticks to

yticks = Join @@ (#[Quiet @ 
  Charting`ScaledTicks[{scF[100, 1/4], iscF[100, 1/4]}][##2, {10, 5}]] & @@@ 
    {{Most, 0, 100}, {Rest, 100, Max@data}});

to get

![enter image description here

| improve this answer | |
$\endgroup$
  • $\begingroup$ This is a very interesting function. Wonder why it is undocumented. $\endgroup$ – Guillermo Oliver May 9 at 19:03
  • $\begingroup$ Is is possible to define different types of 'breaks'? Something else than that seesaw curve? $\endgroup$ – Guillermo Oliver May 9 at 19:05

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.