3
$\begingroup$

while searching for solutions making textures in bar charts possible, I found this code posted by the user halmir here: Hatched bars and bar-specific background in BarChart

Unfortunately this doesn't work for low chart heights, which are smaller than the width of the chart. The term (yt - width) becomes negative and errors appear.

For example:

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

enter image description here

Is there another solution to change the appearance of barcharts? Already tried the approach How to change texture of chart bar? which uses the texture command and images. For big numbers and stacked bar charts it is noch efficient anymore.

If you know an easy approach for changing barcharts, my computer and I would be very thankful:)

Sorry for the huge text & all the best, Kilian

$\endgroup$
1
  • 1
    $\begingroup$ Please add code with a BarChart and data that shows the problem bars, so we don't have to invent a data set etc, $\endgroup$
    – MarcoB
    Jun 28 '18 at 22:09
2
$\begingroup$

If you are only looking for the stripes then you may use HatchFilling in the ChartStyle option.

With

dat = {2, -1, .05, -3, 3, 2.5}

Then

BarChart[dat
 , BarSpacing -> 2
 , ChartStyle -> (Directive[HatchFilling[], ColorData[61, #]] & /@ 
    Range@Length@dat)
 , GridLines -> {None, Automatic}
 ]

Mathematica graphics

HatchFilling added in version 12.1.

For additional fillings see the Filling in 2D section of the Graphics Directives guide.

Hope this helps.

$\endgroup$
1
$\begingroup$

Update: A simpler custom chart element function:

ClearAll[CEF]
CEF[cedf_ : {"Rectangle"}, op_ : .5] :=   
   {Opacity[op], EdgeForm[],  
    (ChartElementData @@ cedf)[{#[[1, 1]] + {0, 1},  
        Charting`ChartStyleInformation["BoundingBox"][[2]]}, ##2], 
    Opacity[1], EdgeForm[Gray], HatchFilling[45 Degree, 3, 10], 
    ChartElementData["Rectangle"][##]} &;

Examples:

dat = {2, -1, .05, -3, 3, 2.5};

BarChart[dat, 
 ImageSize -> 600, 
 GridLines -> {None, Automatic}, 
 ChartStyle -> 61,  
 BarSpacing -> 2, 
 "BarStartingValue" -> 0,
 Axes -> {False, True}, 
 ChartElementFunction -> CEF[], 
 Epilog -> {GrayLevel[.4], AbsoluteThickness[.2], 
   Line[{{0, 0}, {Length @ data, 0}}]}]

enter image description here

Use BarSpacing -> 1 and replace CEF[] with CEF[{"FadingRectangle", "GradientOrigin"->Right}] to get

enter image description here

Original answer:

dat = {2, -1, .05, -3, 3, 2.5};

An alternative approach using HatchFilling as in Edmund's answer and a custom ChartElementFunction to add background fillings:

backgroundCEF[cedf_ : "Rectangle"] :=    
  ChartElementData[cedf][{#[[1, 1]] + {0, 1},  
     Charting`ChartStyleInformation["BoundingBox"][[2]]}, ##2] &;

Note: For this chart element function to work properly, we need to add the (undocumented) option "BarStartingValue" -> 0 in BarChart[...] so that the horizontal coordinates of rectangles are successive integer pairs starting at 0.

Examples:

We can use backgroundCEF in two ways:

  1. Create a separate bar chart with the option ChartElementFunction -> backgroundCEF[] and combine it with the original bar chart using Show, or
  2. Use the graphics primitives of the bar chart created with backgroundCEF[] as Prolog in the original bar chart:

Show[BarChart[dat, ImageSize -> 600, 
   ChartStyle -> 61, 
   ChartBaseStyle -> HatchFilling[],  
   BarSpacing -> 2, 
   "BarStartingValue" -> 0, 
   Axes -> {False, True}], 
 BarChart[dat, ImageSize -> 600,
   ChartStyle -> 61, 
   ChartBaseStyle -> Directive[EdgeForm[], FaceForm[Opacity[.2]]], 
   ChartElementFunction -> backgroundCEF[], 
   BarSpacing -> 2, 
   "BarStartingValue" -> 0], 
  Prolog -> {Line[{#, Scaled[{1, 0}, #]} & @ {0, 0}]}]

enter image description here

BarChart[dat, ImageSize -> 600, 
  ChartStyle -> 61, 
  ChartBaseStyle -> HatchFilling[],  
  BarSpacing -> 2, 
  "BarStartingValue" -> 0, 
  Axes -> {False, True}, 
  PlotRange -> {{0, Length@dat}, All}, 
  Prolog -> {Line[{#, Scaled[{1, 0}, #]} & @ {0, 0}], 
   First @ BarChart[dat, 
      ChartStyle -> 61, 
      ChartBaseStyle -> Directive[EdgeForm[], FaceForm[Opacity[.2]]], 
      ChartElementFunction -> backgroundCEF[], 
      BarSpacing -> 2, 
      "BarStartingValue" -> 0]}] 

enter image description here

Replace FaceForm[Opacity[.2]] with FaceForm[Opacity[.4]] and use backgroundCEF["FadingRectangle] to get

enter image description here

Use backgroundCEF["GlassRectangle] to get

enter image description here

$\endgroup$
0
$\begingroup$

I modified the code of the former posts like this:

barHatched[gap_, h_, seg_, 
color_][{{xmin_, xmax_}, {ymin_, ymax_}}, ___] := 
Module[{width, line, yt, yb, lend}, {yb, yt} = Sort[{ymin, ymax}];
width = xmax - xmin;

line = Table[{{xmin + i, yb}, {xmin + i, yt}}, {i, 0, width, h/seg}];
line = {Line[line]};

{{Opacity[1], EdgeForm[], 
Rectangle[{xmin, ymin}, {xmax + gap, ymax}]}, {color, 
CapForm["Butt"], line}, {FaceForm[], 
Rectangle[{xmin, ymin}, {xmax, ymax}]}}]


barHatched2[gap_, h_, seg_, 
color_][{{xmin_, xmax_}, {ymin_, ymax_}}, ___] := 
Module[{width, line, line2, yt, yb, lend, lend2}, {yb, yt} = 
Sort[{ymin, ymax}];
width = xmax - xmin;

 line = Table[{{xmin, i}, {xmax, i + width}}, {i, yb, yt - width, 
 h/seg}];
 line2 = 
 Table[{{xmin + i, yb}, {xmax, yb + width - i}}, {i, h/seg, width, 
 h/seg}];

 If[yt > width, lend = line[[-1, 1, 2]]];
 lend2 = line2[[1, 1, 2]];

 line = {If[yt > width, Line[line]],

 Line[Table[{{xmin + i, yb}, {xmax, yb + width - i}}, {i, h/seg, 
   width, h/seg}]],

 If[yt > width, 
 Line[Table[{{xmin, lend + i}, {xmax - (lend + width - yt) - i, 
     yt}}, {i, h/seg, width, h/seg}]],
 Line[
  Table[{{xmin, yb + i}, {xmin + yt - i, yt}}, {i, 0, yt, h/seg}]]]


  };

 {{Opacity[.2], EdgeForm[], 
  Rectangle[{xmin, ymin}, {xmax + gap, ymax}]}, {CapForm["Butt"], 
  line}, {FaceForm[], Rectangle[{xmin, ymin}, {xmax, ymax}]}}]

In cases ymax < width some changes had to be made. So it also works for lists with amounts smaller than the width of bars. Thanks for asking and offering your help!!

$\endgroup$
1
  • 3
    $\begingroup$ Is this an answer or additional information for the original post? I ask because it's not clear what the original issue is and therefore it's not clear if the above is an answer or not. (It's certainly fine and encouraged to answer one's own questions.) It seems that a graphic illustrating the problem would be very helpful. $\endgroup$
    – JimB
    Jun 28 '18 at 23:32
0
$\begingroup$
dat = {2, -1, .05, -3, 3, 2.5};

Yet another approach is to construct background rectangles directly and use them as Prolog in BarChart (and add the option "BarStartingValue" -> 0):

colors = ColorData[61] /@ Range[Length @ dat];

xaxis = Line[{#, Scaled[{1, 0}, #]} & @ {0, 0}];

backgroundRectangles = MapThread[
   {Opacity[.2], #, Rectangle[Scaled[{0, -1}, First@#2], Scaled[{0, 1}, Last@#2]]} &, 
  {colors, Partition[Thread[{Range[0, Length @ dat], 0}], 2, 1]}];

BarChart[dat, 
 ImageSize -> 600, 
 ChartStyle -> 61, 
 ChartBaseStyle -> HatchFilling[],  
 BarSpacing -> 2, 
 "BarStartingValue" -> 0, 
 Axes -> {False, True}, 
 PlotRange -> {{0, Length @ dat}, All}, 
 Prolog -> {xaxis, backgroundRectangles}]

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.