Creating overlapping histogram plots

Doesn't Histogram do this already?

data1 = RandomReal[NormalDistribution[0, 1], 500];
data2 = RandomReal[NormalDistribution[1, 1.5], 500];

Histogram[{data1, data2}]

Mathematica graphics


Version 7 doesn't have HistogramDistribution as shown by Andy Ross. Here is an alternative:

Histogram[{data1, data2},
  BaseStyle  -> FaceForm[None],
  ChartStyle -> {EdgeForm[{Thick, Red}], EdgeForm[{Thick, Blue}]}
]

Mathematica graphics


jmlopez asked for a method without the vertical lines. Here is one. The replacement may be a bit fragile. Andy's method is safer for version 8 users.

Update: modified to work in Mathematica 10 as well.

h =
 Histogram[{data1, data2},
   ChartStyle -> (Directive[#, AbsoluteThickness[3]] & /@ {Red, Blue}),
   PerformanceGoal -> "Speed"
 ];

h2 =
 Histogram[{data1, data2},
   ChartStyle -> {{Red, Blue}, Directive[Opacity[0.1], EdgeForm[]]}
 ];

hline = h /. rec : {({{_Rectangle}} | {}) ..} :>
  Line[  Flatten[rec, 2] /. _[{x_, y_}, {X_, Y_}, ___] :> Sequence[{x, Y}, {X, Y}]  ];

Show[hline, h2]

Mathematica graphics


kjo pointed out that my method fails when bars have a height of zero. The simplest fix I can think of is to avoid zero-height bars (which are not drawn, the source of the problem) by using a small offset value for the hspec function.

hfn = $MachineEpsilon + #2 &;

h = Histogram[{data1, data2}, {0.1}, hfn, 
  ChartStyle -> (Directive[#, AbsoluteThickness[3]] & /@ {Red, Blue}), 
  PerformanceGoal -> "Speed"]

h2 = Histogram[{data1, data2}, {0.1}, hfn, 
  ChartStyle -> {{Red, Blue}, Directive[Opacity[0.1], EdgeForm[]]}]

hline = h /. 
   rec : {({{_Rectangle}} | {}) ..} :> 
    Line[Flatten[rec, 2] /. _[{x_, y_}, {X_, Y_}, ___] :> Sequence[{x, Y}, {X, Y}]];

Show[hline, h2]

enter image description here


You also have the option of SmoothHistogram.

data1 = RandomVariate[NormalDistribution[0, 1], 10^3];
data2 = RandomVariate[NormalDistribution[.4, 1], 10^3];

SmoothHistogram[{data1, data2}, 
 PlotStyle -> {{Thick, Red}, {Thick, Blue}}]

enter image description here

Or using one of the nonparametric distributions HistogramDistribution...

Plot[Evaluate[{PDF[HistogramDistribution[data1], x], 
   PDF[HistogramDistribution[data2], x]}], {x, -4, 4}, 
 Exclusions -> None, PlotPoints -> 100, 
 PlotStyle -> {{Thick, Red}, {Thick, Blue}}]

enter image description here


First method

You could make the one in front partially transparent:

bc = RandomVariate[NormalDistribution[], 1000];
bcx = RandomVariate[NormalDistribution[], 1000];

g1 = Histogram[bc, ChartStyle -> {Red}];
g2 = Histogram[bcx, ChartStyle -> {Directive[Blue, Opacity[.5]]}];
Show[g1, g2, PlotRange -> All]

Mathematica graphics

Direct method

The same effect can be achieved by plotting the two distributions in the same plot directly:

Histogram[{bc, bcx}, ChartStyle -> {Red, Blue}]

Tags:

Plotting