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 am trying to create a BarChart visualization for multi-step data filtering. Think of a traditional sales funnel: many leads, fewer prospects, few customers, very few return customers. The only kicker is, I want to show the percentage of data being lost by using Percentile layout for the BarChart, and I want to show that the slice of previous bar is the entirety of the content of the next bar using lines similar to Joined option, and if possible, fill the joining lines with color similar to the one used for selection. Lastly,for my data content, there are 2 types of filters: binary (e.g. lead becomes prospect or not) and slice-of-pie (e.g. customers who spent between X and Y, where the slice would appear in the middle of the column, with rest of sales with lower amount appearing below, and higher amount appearing above). I can draw this using Graphics and basic primitives, but was really hoping that there's a clever way to adapt BarChart, so that I could use the built-in labeling or legending features, as well as the vertical axis. Or even go from Percentile to Stacked, as needed.

Here's a simple drawing of what I envision this could look like: Example of funnel barchart

And if anyone can suggest an alternate visualization which will serve the purpose, I'd really appreciate it. I thought of using TreeGraph with VertexSize option, but it's less than trivial to visualize not only what made it into the filter, but also how much are you losing and where the loss occurs.

UPDATE:

Thanks to @Verbeia's clever solution, and a little bit of additional engineering, this is what I came up with. Clearly there's endless room for improvement, but the automation works great.

data = {{4, 3, 4.5, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 3, 5, 6, 0, 
    0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 1, 2, 3, 0, 0, 0}, {0, 0, 0, 0,
     0, 0, 0, 0, 0, 1, 1, 1}};
lines = Flatten[Table[{
     {{1.501 n, 
       100 data[[n, 3 n - 2]]/Total@data[[n]]}, {1.5 n + .499, 
       0}}, {{1.501 n, 
       100 (data[[n, 3 n - 2]] + data[[n, 3 n - 1]])/
        Total@data[[n]]}, {1.5 n + .499, 100}}}
    , {n, 1, 3}], 1];

Show[
  BarChart[data, ChartLayout -> "Percentile", 
   BarSpacing -> {None, .5}, ChartStyle -> "Pastel"],
  ListLinePlot[lines, 
   Filling -> 
    Table[(2 n - 1) -> {{2 n}, 
       Directive[Opacity@0.75, 
        ColorData["Pastel"][(3 n - 2)/(3 4)]]}, {n, 1, 3}], 
   PlotStyle -> Directive[Dashed, Gray]]
  , ImageSize -> 850]

And the result:

funnel_barchart_new

share|improve this question
add comment

1 Answer

up vote 7 down vote accepted

The built-in Joined option to BarChart doesn't really do what you want. So what I'd suggest is overlaying a BarChart on a ListLinePlot that creates the lines. Here is a simplified two-stacks-of-bars version.

data = {{4, 3, 0, 0, 4.5}, {0, 3, 5, 6, 0}};

The first point is that you will need to have zero-value elements in the bar chart data to ensure you get different coloring in the different stacks, or else use Style explicitly to customise the coloring in each stack.

Then you need to come up with lines that draw between the bars. This might be able to be automated, but it would require knowledge of which bar segments are the ones that "expand" to the next stack, as well as the BarSpacing option value in the BarChart, which determines the horizontal coordinates of the bars.

lines = {{{1, 100 data[[1, 1]]/Total[data[[1]] ]}, {1.5, 
 100 data[[1, 1]]/Total[data[[1]] ]}, {1.7, 0}}, 
{{1, 100 (data[[1, 1]] + data[[1, 2]])/Total[data[[1]] ]}, 
{1.5, 100 (data[[1, 1]] + data[[1, 2]])/Total[data[[1]] ]}, {1.7,  100}}};

Putting them together is fairly straightforward, but watch the PlotRange and Filling options in the ListLinePlot function:

Show[ListLinePlot[lines, PlotRange -> {{0, 3}, {0, 101}}, Filling -> {2 -> {1}}],
 BarChart[data, ChartLayout -> "Percentile"]]

enter image description here

share|improve this answer
1  
+1 Maybe with PlotStyle -> None in ListLinePlot[ ]. –  Silvia Jun 27 '13 at 7:36
    
Or PlotStyle -> Dashed in ListLinePlot. –  David Carraher Jun 27 '13 at 7:59
1  
Or even using arrows instead of lines: data = {{4, 3, 0, 0, 4.5}, {0, 3, 5, 6, 0}}; arrows = {Dashed, Arrow[{{1.5, 100 data[[1, 1]]/Total[data[[1]]]}, {1.7, 0}}], Arrow[{{1.5, 100 (data[[1, 1]] + data[[1, 2]])/Total[data[[1]]]}, {1.7, 100}}]}; Show[BarChart[data, ChartLayout -> "Percentile"], Graphics[arrows, PlotRange -> {{0, 3}, {0, 101}}]] –  David Carraher Jun 27 '13 at 8:16
    
@Verbeia: clever use of 0s in the BarChart, to hide slices of color!!! Very nice! Issue that I have with your solution, and perhaps you can enlighten me... your 1.5 number is hard-coded. As I add a custom number of bars to the plot, or as BarChart options change, I really don't know what that distance between bars will be. I can have anywhere from 1 bar (no lines) to a dozen bars or more (rare), with 4-6 bars being a very common scenario. –  Gregory Klopper Jun 27 '13 at 22:58
    
Nevermind, I actually see that any number of columns is created using the same spacing: 0.5 + (1+0.2)x#bars. I can now create a function to convert a list of any number of filters (2 or 3 elements) into lines and bars. and if I stack their order: {1,2,0,0,0,0,0},{0,0,3,4,5,0,0},{0,0,0,0,0,6,7}, I can apply any number of colors I want. Same with the lines, if I make them all separate lines, I can control colors with FillingStyle. WIN! Thank you! –  Gregory Klopper Jun 27 '13 at 23:05
show 3 more comments

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.