Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I can plot an ordinary histogram with blue shading and black borders like this:

T = RandomVariate[NormalDistribution[0, 1], 10000];
Histogram[T, 30]

And I can simulate hatching like this:

T = RandomVariate[NormalDistribution[0, 1], 10000];
Histogram[T, 30, ChartElements -> Graphics[{Black, Line[{{0, 0}, {1, 1}}]}]]

How can I get the hatching and the black borders at the same time?

share|improve this question
add comment

4 Answers

up vote 17 down vote accepted

I was sure Histogram can be modified to have the hatching style. Little late but what about this!

g[{{xmin_, xmax_}, {ymin_, ymax_}}, ___] := Module[{yval, line},
  yval = Range[ymin, ymax, 15];
  line = Line /@ Transpose@{Most@({xmin, #} & /@ yval),Rest@({xmax, #} & /@ yval)};
  {FaceForm[White],Polygon[{{xmin, ymin}, {xmax, ymin}, {xmax, ymax}, {xmin, ymax}}],
   Orange, line}];
T = RandomVariate[NormalDistribution[0, 1], 10000];
Histogram[T, 30, ChartElementFunction -> g,
ChartBaseStyle -> EdgeForm[{Thin, Darker@Orange}], Frame -> True]

enter image description here

Check in the function where yval is defined with Range[ymin, ymax, 15] one can change the $15$ to change the amount of hatching. You also have total control of the Graphics primitive used in the ChartElementFunction so you can use many more Directive for example Opacity and all.

BR

share|improve this answer
    
Hah. What I was going to do, but ran out of time! +1 –  rcollyer Aug 27 '13 at 15:43
    
@rcollyer Thx! TThough the Show based solution is simpler I thought of trying this solution. –  PlatoManiac Aug 27 '13 at 16:44
    
I upvoted that one, too, as it worked. But, I have an aversion to running things more than once, if I can help it, unless the result is a dramatic speed-up, and the Show method runs it twice. –  rcollyer Aug 27 '13 at 17:05
    
This twice thing of Show forced me to do this! –  PlatoManiac Aug 27 '13 at 17:20
add comment

I would do something like:

t = RandomVariate[NormalDistribution[0, 1], 10000];
a = Histogram[t, 30, ChartStyle -> White];
b = Histogram[t, 30, 
  ChartElements -> Graphics[{Black, Line[{{0, 0}, {1, 1}}]}]];
Show[a, b]

enter image description here

share|improve this answer
add comment

You can use the PDF of a HistogramDistribution for the outline.

dist = HistogramDistribution[T, 30]

p1 = Plot[PDF[dist, t], {t, -4, 4}, PlotStyle -> Black, 
   Exclusions -> None, PlotPoints -> 100];

p2 = Histogram[T, 30, "PDF", 
   ChartElements -> Graphics[{Black, Line[{{0, 0}, {1, 1}}]}]];

Show[p1, p2]

enter image description here

The problem here is that it isn't a frequency histogram but a density histogram.

If you want to get counts you need to multiply by the bin width and sample size.

p1 = Plot[
  Differences[dist["BinDelimiters"]][[1]]*10^4*PDF[dist, t], {t, -4, 
   4}, PlotStyle -> Black, Exclusions -> None, PlotPoints -> 100]

enter image description here

Edit:

If you don't want to use HistogramDistribution you can also try HistogramList.

ListLinePlot[
 Thread[{Most[First[#]], Last[#]}] &[HistogramList[T, 30]], 
 InterpolationOrder -> 0, PlotStyle -> Black]
share|improve this answer
add comment

Here is extended version of PlatoManiac's solution which allows changing of the direction of the hatching and also tuning the distance between hatches:

g[step_?NumberQ][{{xmin_, xmax_}, {ymin_, ymax_}}, ___] := 
  Module[{yval, lines, xstart, xend},
   yval = Range[ymin, ymax, Abs[step]];
   If[step > 0, {xstart, xend} = {xmin, xmax}, {xstart, xend} = {xmax, xmin}];
   lines = Transpose@{{xstart, #} & /@ Most[yval], {xend, #} & /@ Rest[yval]};
   lines = Join[lines, {{{xstart, Last@yval}, 
           {xstart + ((xend - xstart) (ymax - Last@yval))/Abs[step], ymax}}}];
   {FaceForm[None], Rectangle[{xmin, ymin}, {xmax, ymax}], 
                                               CapForm["Butt"], Line[lines]}];

Now

data = RandomVariate[NormalDistribution[0, 1], 10000];
Histogram[data, 30, "PDF", ChartElementFunction -> g[-.006], 
 ChartBaseStyle -> {Directive[{EdgeForm[{Thin, Black}], Black}]}, 
 Frame -> True]

gives

hist

And now one can combine several histograms with different hatchings:

data1 = RandomVariate[NormalDistribution[0, 1], 500];
data2 = RandomVariate[NormalDistribution[2, 1/2], 500];
h1 = Histogram[data1, 30, "PDF", ChartElementFunction -> g[.0260], 
   ChartBaseStyle -> Directive[{EdgeForm[{Thin, Black}], Black, Thin}], 
   Frame -> True];
h2 = Histogram[data2, 30, "PDF", ChartElementFunction -> g[-.0180], 
   ChartBaseStyle -> Directive[{EdgeForm[{Thin, Black}], Black, Thin}], 
   Frame -> True];
Show[h1, h2, PlotRange -> All, BaseStyle -> Antialiasing -> False]

2 hists

The histogram can be optimized by joining adjacent line segments into solid lines and deleting auxiliary points. Here is an example:

data = RandomVariate[NormalDistribution[0, 1], 100];
hist = Histogram[data, 30, "PDF", ChartElementFunction -> g[-.0160], 
  ChartBaseStyle -> {Directive[{EdgeForm[{Thin, Black}], Black}]}, Frame -> True];

hatchings = Cases[hist, (Line | LineBox)[{x__List}] /; Dimensions[{x}][[2]] == 2 :> x, {0, Infinity}];
hist2 = DeleteCases[hist, (Line | LineBox)[{x__List}] /; Dimensions[{x}][[2]] == 2, {0, Infinity}];

ClearAll[coeff, a, b, x1, x2, y1, y2];
coeff[{{x1_, y1_}, {x2_, y2_}}] /; x1 != x2 = {a, b} /. First@Solve[{a x1 + b == y1, a x2 + b == y2}, {a, b}];
Show[hist2, 
 Graphics[{Line@
    Flatten[Map[SortBy[Flatten[#, 1], Last][[{1, -1}]] &, 
      (Split[#, #1[[2]] == #2[[1]] || #1[[1]] == #2[[2]] &] & /@ 
        Gather[hatchings, coeff[#1] == coeff[#2] &]), {2}], 1]}]]

screenshot

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.