Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Funnel charts #3504

Closed
nicolaskruchten opened this issue Feb 1, 2019 · 57 comments · Fixed by #3876
Closed

Funnel charts #3504

nicolaskruchten opened this issue Feb 1, 2019 · 57 comments · Fixed by #3876
Assignees
Milestone

Comments

@nicolaskruchten
Copy link
Contributor

Funnel charts are kind of interesting because they're kind of like stacked bar charts, with variable width bars, often with sloping sides, which makes for the potential for double-encoding. A standard stacked bar chart has each segment with the same width, and the height of the segment encodes the datum. On the other extreme you can have bars where each are the same height, and the width encodes the datum, like this: https://www.amcharts.com/demos/funnel-chart/

In both of those cases, the area is proportional to the datum. If you start sloping the sides, then the area no longer matches the datum and it's just the height: https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/demo/funnel/

So we could maybe add some options to bar to make the version without sloping sides, but it may make more sense to create a new trace type here. We'll want some special legend and color handling, as well as some computations for hovertemplate like 'percentage of total' and 'percentage difference with previous stage' etc.

@nicolaskruchten
Copy link
Contributor Author

Another way to think about funnels is as lines... The point where two stages meet is the datum in this case, and the sloped segment between the points indicates the 'rate of loss' between points.

@alexcjohnson
Copy link
Collaborator

I really dislike the version where the whole side is sloped - I get that this makes the analogy to an actual funnel clearer, but it makes the data value highly ambiguous. But connecting bars with a sloping region in the gap, like the amcharts example does, strikes me as really cool, and would be a nice addition to regular bar charts too. This came up recently, I can't seem to find it now, but it's a great effect for stacked bars with some sort of stack sorting, because it shows you when two series change order in the stack.

At that point it would be fairly easy to imagine this just as another attribute to a bar chart to shift it to symmetric about the size-axis origin, but perhaps enough of the default attributes should change that it's worth making a trace type for it (and just use the bar code to render it)

@nicolaskruchten
Copy link
Contributor Author

Yup, that about sums up my feelings after writing this up. I wonder if a new trace type might not be better just in terms of usability, rather than having to juggle x and y etc. Also right now this would have to be trace-per-funnel-stage to get the stacking right, which is awkward, so maybe a funnel is more like a pie than a bar actually, in terms of the colouring and stacking behaviour.

@alexcjohnson
Copy link
Collaborator

Oh I was thinking of this not as stacked at all, but a single trace of horizontal bars of equal height. That's how the amcharts example does it, and it shows you all the relevant information clearly: the total starting size, the size and amount lost at each stage, and it's intuitive that each stage is a subset of the previous stage.

The way that highcharts example shows it, where the vertical size of each segment is different, strikes me as totally inappropriate. Yes, it shows you the size at each stage (at least if you can figure out how to interpret the sloping sides), but the total stack size is completely meaningless and there's no way to visually see what's lost at each stage.

@nicolaskruchten
Copy link
Contributor Author

nicolaskruchten commented Feb 1, 2019

OK, so then a pie-like thing makes sense, if we want to be able to let people have different colours for each stage. I actually think that separate legend items per stage could be problematic if we allow click-to-hide :)

@alexcjohnson
Copy link
Collaborator

Related potential use for a bar trace positioned symmetrically about the origin of the size axis: check out the "neutral" trace here https://peltiertech.com/charting-survey-results/:

screen shot 2019-02-01 at 2 27 12 pm

The final piece we'd need to make this plot I guess is an attr to say "stack this trace on the negative side" for the "hate" and "dislike" traces. Or perhaps that would happen automatically if "neutral" is the third trace in the stack but it has an attribute saying "position this trace symmetrically"?

@nicolaskruchten
Copy link
Contributor Author

So what can we converge on in terms of an API here? The key question in my mind is: is this pie-like in the sense that one funnel = one trace? Or bar-like in the sense that one funnel stage = one trace?

In general I feel like this is quite pie-like, even perhaps to the point of not actually rendering axes etc.

@alexcjohnson
Copy link
Collaborator

Definitely one funnel = one trace. I'm not sure it has any practical implications but to my mind it's much more like horizontal bars than pie. Perhaps we don't draw them by default, but I certainly think we want it drawn on cartesian axes, so that you can overlay it with other traces matching at least the category axis, and probably so you can stack funnels like https://stackoverflow.com/questions/45421748/making-a-stacked-funnel-chart-in-excel
screen shot 2019-02-04 at 10 37 50 am

@nicolaskruchten
Copy link
Contributor Author

Ok for one funnel per trace. It’s very common to want each bar a different color however (much more than to segment each bar like in the image above) so I would want built in support for this, like in pie.

@archmoj archmoj self-assigned this Mar 14, 2019
@nicolaskruchten
Copy link
Contributor Author

  • new trace type
  • bar-length encoding only, no variable width
  • no neck.
  • ability to center the thing
  • no negative values
  • accepts stacking, grouping, overlaying
  • x, y (cartesian subplots) with magic to hide the grids
  • ability to display on-plot and/or in hover the "percentage of first" and "percentage of previous"
  • connecting lines
  • ability to hover on connecting area to see delta in hover
  • ability place delta% text on the intermediate area

@chriddyp
Copy link
Member

  • in addition to the delta% (from one stage to the next), it seems like many of the charts have percentages based off the value (value / total)

image

@nicolaskruchten
Copy link
Contributor Author

So that's interesting: I guess there are two ways of seeing funnel charts.

It's either "each step contains a subset of the previous step" meaning each unit appears in N stages. Or it's "each step contains a unit in its current position" meaning each unit is accounted for in one stage at a time.

@nicolaskruchten
Copy link
Contributor Author

Note that at the moment we're not considering building the ability to make the above chart with the sloping sides, as it's very ambiguous/incorrect to encode something with height while you're narrowing the width. @chriddyp do you think it's very important to support this kind of thing with a constant slope?

@alexcjohnson
Copy link
Collaborator

Right, I guess that's like "here's what's in our sales funnel right now" in which case "total" does have a real meaning, it's the sum of all deals the team is working on. But there's also no need that successive stages must decrease in size - averaged over time they would, but that's not necessarily true in one snapshot because they refer to different items.

@nicolaskruchten
Copy link
Contributor Author

nicolaskruchten commented Mar 26, 2019

OK, so after chatting with @chriddyp I think we should actually do something fairly different from what we (enjoyably!) discussed last Thursday. I'm now seeing funnel traces as trapezoid-shaped area-encoded pie traces rather than a specialization of bar charts. Should be easier to implement actually, just lift all the non-circular aspects of the pie API. Update: never mind, see below!

@alexcjohnson
Copy link
Collaborator

The pie analogy works for the snapshot case but I don’t see how it handles the successive parts of a whole case. Want to elaborate on the API you’re imagining?

@nicolaskruchten
Copy link
Contributor Author

(still discussing with @chriddyp actually, but basically we would not support the successive parts of whole case if we went pie-like, @alexcjohnson )

@nicolaskruchten
Copy link
Contributor Author

OK, discussion concluded... original plan still stands.

Let's add one more bullet though:

  • a flag to enable sloping sides on the bars like this, such that the bars are still length-encoded to the midpoint, and area-encoded, AND we have sloped sides

image

@nicolaskruchten
Copy link
Contributor Author

nicolaskruchten commented Mar 26, 2019

If we wanted a pie-like funnel we could create a second funnelarea trace type or something.

@antoinerg
Copy link
Contributor

If we wanted a pie-like funnel we could create a second funnel_area trace type or something.

Isn't a pie-like funnel a sunburst trace? Pretty cool example: https://bl.ocks.org/kerryrodden/7090426

@nicolaskruchten
Copy link
Contributor Author

Isn't a pie-like funnel a sunburst ?

Not really: I meant in the sense of "parts of whole"

@alexcjohnson
Copy link
Collaborator

FYI in whatever program produced that example, the value is encoded in the max width, not the area. Look what happens when you overlay the two sides:
Screen Shot 2019-03-26 at 6 10 38 PM

In fact I think if you area-encode with constant thickness, you're forced into strange situations like a boundary line bigger than the one above despite the same or smaller value. Consider a step 100-100-100-50-50-50, there's an extra degree of freedom (you could make the 100's look better if the 50's look worse) but I think you'll always get stuff like this (grey is the midpoint to show value encoding):
Screen Shot 2019-03-26 at 6 34 22 PM

@nicolaskruchten
Copy link
Contributor Author

Surely there is a stable optimum such that all points along the edge are connected with minimum internal angles, that doesn’t look nearly as jagged as your thing above.

@nicolaskruchten
Copy link
Contributor Author

Maybe not though... I see that two equally sized adjacent bars causes a problem.

@alexcjohnson
Copy link
Collaborator

Yeah my example is ridiculous, but that's the point, I really don't think you can do better. There's only one extra degree of freedom so if you make the 100s look better the 50s look worse, and vice versa.

Using the max width is visually appealing because the last bar is straight so the overall chart looks like a physical funnel, but interpretation is bizarre, you have to read it as something like "at this stage we have value Y but then in the next stage it's going to drop to Z."

Could we get away with sloped connectors between rectangular data bars, like the amcharts example? That way the stage values and inter-stage reductions are separate visual elements and it's all very clear what's what.

I suppose another option that might make more intuitive sense would be to encode the value in the minimum width of the trapezoid. That way you can read each stage fairly naturally as "at this stage we reduced from value X (the previous stage) to value Y (this stage). So looking at that one trapezoid you can see the two key metrics for the stage: the remaining value and what was lost getting there. The disadvantage though is people who are used to the dumb but more common max-width encoding would be disoriented.

@nicolaskruchten
Copy link
Contributor Author

Right. OK let' stick with normal rectangular bars and rely on diagonal connectors to make things look funnel-y.

@archmoj
Copy link
Contributor

archmoj commented Apr 3, 2019

In respect to conversation above, this thing appear to be quite similar to bar.
I also like a pie variation of it. But that would become another creature.
What about the colouring options? Markers + Lines + Colorscale?

@nicolaskruchten
Copy link
Contributor Author

OK so let's focus on the bar version now and leave out anything pie-like.

Yes, we will need to be able to specify the marker as a bar: color, length, line-width, line-color etc. We will also need to be able to specify the connector-lines and connector-fill, as well as the bar gap and width etc. (similar to waterfall in a way). Orientation as well.

@nicolaskruchten
Copy link
Contributor Author

Very nice! I would remove connector.mode: I think we should support only "between"

@archmoj
Copy link
Contributor

archmoj commented Apr 15, 2019

What about negative sizes? For the moment one could pass negative sizes and the connectors intersect. But in that case (& if we want to support them then) we may need another color container...

@nicolaskruchten
Copy link
Contributor Author

See above: we said “no negative values”... doesn’t make sense semantically in a funnel.

@alexcjohnson
Copy link
Collaborator

FWIW pie simply ignores negatives, but here the space still has to exist. Shall we simply treat them as zero values?

@archmoj
Copy link
Contributor

archmoj commented Apr 16, 2019

Thanks @alexcjohnson for the pointer to pie.
The negative values are now treated as bad input numbers i.e. BADNUM during calc step.
Updated codepen.

@nicolaskruchten
Copy link
Contributor Author

For both funnel and funnelarea we should have fairly robust textinfo options (see also #3777) so as to be able to display computed values on-chart.

Note that I think that for funnel we should leave the percentages out of the hoverlabel by default and have hoverinfo/textinfo support for percentage-of-first AND percentage-of-total and then let the user choose. (for funnelarea obviously we will support percentage-of-total also).

For funnelarea shape control, I propose that the length of the top of the funnel be sized according to the domain, and then we can have a single attr for "length of bottom as fraction of top". thoughts?

@archmoj
Copy link
Contributor

archmoj commented Apr 19, 2019

New funnel prototype with textinfo and textposition default to auto. Connector mode is no longer needed since the spanning mode is dropped and the only connector mode is between.

@archmoj
Copy link
Contributor

archmoj commented Apr 23, 2019

updated funnel prototype with auto hide axis when there are only funnels visible in data.

@etpinard
Copy link
Contributor

@archmoj looking good - which branch is that on?

@archmoj
Copy link
Contributor

archmoj commented Apr 23, 2019

@etpinard thanks for looking at it. That is on https://github.com/plotly/plotly.js/tree/funnel-finalist

@archmoj
Copy link
Contributor

archmoj commented Apr 23, 2019

Second prototype of the day now it is possible to center the inside text using insidetextcenter: true.
I am not a fan of defaulting it to true considering overaly & group modes.

@archmoj
Copy link
Contributor

archmoj commented Apr 24, 2019

New prototype with filled in-between areas i.e. thanks to @nicolaskruchten feedback.

@nicolaskruchten
Copy link
Contributor Author

Oh yeah, so nice! can we default the text to not rotate like it does? i.e. stay horizontal?

@nicolaskruchten
Copy link
Contributor Author

For textinfo: I think we need to distinguish between "percentage of total" and "percentage of previous" and allow people to specify both/either/neither.

@alexcjohnson
Copy link
Collaborator

distinguish between "percentage of total" and "percentage of previous"

Perhaps also "percentage of first", like this one?
Screen Shot 2019-04-24 at 3 50 14 PM

@archmoj
Copy link
Contributor

archmoj commented Apr 24, 2019

@nicolaskruchten Good point related to textinfo. Instead of "total" which refers to the first value in data, could we use "initial" for example: initial percent & delta percent if 'spaces' are allowed for flags?
And what about hover?

@alexcjohnson
Copy link
Collaborator

"total" which refers to the first value in data

or to the sum of all values...

@archmoj
Copy link
Contributor

archmoj commented Apr 24, 2019

"total" which refers to the first value in data

or to the sum of all values...

Yes that can make sense too. So should we have all the 3 rather similar to waterfall and this PR?

@nicolaskruchten
Copy link
Contributor Author

Right I forgot pct of first of course

@nicolaskruchten
Copy link
Contributor Author

And yes this should be available to hoverinfo AND hovertemplate please

@archmoj
Copy link
Contributor

archmoj commented Apr 25, 2019

Here is the updated prototype which displays those 3 ratios.

@archmoj
Copy link
Contributor

archmoj commented Apr 25, 2019

And this the development branch: fix3777-textinfo-waterfall-fin...funnel-new-proto .

@archmoj
Copy link
Contributor

archmoj commented Apr 25, 2019

Updated prototype with cliponaxis: false & other fixes.
Also in the textinfo the percent description is not printed when only one of the percentage flags are used.

@etpinard
Copy link
Contributor

@archmoj I gave your fix3777-textinfo-waterfall-fin...funnel-new-proto a first look. It's looking pretty good!

I only noticed two "major" things:

Once these are addressed, please PR away 🚀 The other comments are minor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants
@nicolaskruchten @antoinerg @chriddyp @alexcjohnson @etpinard @archmoj and others