8
$\begingroup$

I would like to diagonally hatch the bars in BarChart and to have three different background colors for the different bars, like this:

enter image description here

Any ideas how to reproduce this image? The closest post I found is here.

$\endgroup$
4
  • 4
    $\begingroup$ Related: How do I plot a histogram with hatched shading? $\endgroup$
    – rm -rf
    Oct 15, 2013 at 4:35
  • $\begingroup$ @rm-rf The hatching part of this question is a duplicate indeed. The background part, however, is unique to this question. Therefore, I hesitate to vote to close. $\endgroup$ Oct 15, 2013 at 6:29
  • $\begingroup$ @SjoerdC.deVries Fair enough. Changed comment to "Related" $\endgroup$
    – rm -rf
    Oct 15, 2013 at 7:05
  • $\begingroup$ Since v12.1 HatchFilling can be used in BarCharts $\endgroup$ Mar 18, 2020 at 21:55

2 Answers 2

15
$\begingroup$

With a bit of manual parameters:

barFilled[gap_, h_, seg_][{{xmin_, xmax_}, {ymin_, ymax_}}, ___] := 
 Module[{width, line, yt, yb, lend},
  {yb, yt} = Sort[{ymin, ymax}];
  width = xmax - xmin;
  line = Table[{{xmin, i}, {xmax, i + width}}, {i, yb, yt - width, h/seg}];
  lend = line[[-1, 1, 2]];
  line = {Line[line],
     Line[Table[{{xmin + i, yb}, {xmax, yb + width - i}}, {i, h/seg, width, h/seg}]], 
     Line[Table[{{xmin, lend + i}, {xmax - (lend + width - yt) - i,yt}}, {i, h/seg, width + h/seg, h/seg}]]};
   {{Opacity[.2], EdgeForm[], Rectangle[{xmin, -h}, {xmax + gap, h}]},
    {CapForm["Butt"], line}, {FaceForm[], Rectangle[{xmin, ymin}, {xmax, ymax}]}}]

BarChart[{2, -1, 1.5, -3, 3, 2.5}, BarSpacing -> 2, 
 ChartElementFunction -> barFilled[.65, 3, 35], ChartStyle -> 61, 
 GridLines -> {None, Automatic}]

enter image description here

Like AimForClarity mentioned, to avoid empty strip, we could replace 0 with some dummy value + meta and define barFilled for that value. For example:

barFilled[gap_, h_, seg_][{{xmin_, xmax_}, {ymin_, ymax_}}, _, {None}] :=
 {{Opacity[.2], EdgeForm[], Rectangle[{xmin, -h}, {xmax + gap, h}]}}

BarChart[{2, -1, 0, -2, 1, 2} /. {0 -> (1 -> None)}, BarSpacing -> 2,  ChartElementFunction -> barFilled[.65, 2, 35], 
ChartStyle -> 61, GridLines -> {None, Automatic}]

enter image description here

$\endgroup$
7
  • $\begingroup$ Does the grid lines have to be on top of the charts and axes ticks labels? $\endgroup$
    – mmal
    Oct 15, 2013 at 8:45
  • $\begingroup$ @mmal grid lines are behind bars. It's a side effect of setting FaceForm[]. If you don't want that, you can insert one more rectangle before drawing lines. For example, .., {FaceForm[White], Rectangle[{xmin, ymin}, {xmax, ymax}]}, {CapForm["Butt"], line}, ... $\endgroup$
    – halmir
    Oct 15, 2013 at 12:14
  • 2
    $\begingroup$ @mmal To have grid lines on top of the charts and axes ticks labels one can use Method -> {"GridLinesInFront" -> True} option. $\endgroup$ Oct 15, 2013 at 21:12
  • $\begingroup$ Thanks, the halmir's method does exactly what I was thinking about. Using Frame->True clips the grid lines to frame region. $\endgroup$
    – mmal
    Oct 16, 2013 at 5:52
  • $\begingroup$ I hav not been able to get around this silly problem, that if one of the elements is 0 in the array, the barFilled function does not seem to be called and so there is an empty strip, any ideas how to fix this? $\endgroup$ Oct 19, 2013 at 4:31
4
$\begingroup$

We can use ChartBaseStyle -> HatchFilling[] (HatchFilling is introduced in version 12.1) to get rectangles with hatched filling. Using the (undocumented) option "BarStartingValue" -> 0 the horizontal coordinates of bars become successive integers starting with 0 (independent of the BarSpacing option value). Then, it becomes an easy task to get the coordinates of the background rectangles using Scaled to construct epilog primitives:

epilog[col_] := MapIndexed[{Opacity[.2], #, 
     Rectangle[Scaled[{0, -1}, {#2[[1]] - 1, 0}], Scaled[{0, 1}, {#2[[1]], 0}]]} &, 
   col]

Examples:

data = {2, -1, 1.5, -3, 3, 2.5};
colors = ColorData[61] /@ Range[Length @ data];

BarChart[data, 
   ChartBaseStyle -> HatchFilling[], 
   BarSpacing -> 2, 
   ChartStyle -> 61, Axes -> {False, True}, 
   GridLines -> {None, Automatic}, 
   PlotRange -> {{0, Length @ data}, All},
   "BarStartingValue" -> 0,
   Epilog -> {Line[{{0, 0}, {Length @ data, 0}}],
     epilog[PadRight[colors, Length @ data,colors]]}]

enter image description here

Use BarSpacing -> 1 to get

enter image description here

With data = {2, -1, 0, -3, 3, 2.5}; we get

enter image description here

$\endgroup$

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.