evidence-dev / evidence

Business intelligence as code: build fast, interactive data visualizations in pure SQL and markdown
https://evidence.dev
MIT License
3.44k stars 167 forks source link

100 percent stacked bar and area charts #354

Closed hughess closed 1 year ago

hughess commented 1 year ago

This PR implements 100% stacked bar and area charts using the type prop (type=stacked100).

How It Works

Other Changes

Current Limitations

changeset-bot[bot] commented 1 year ago

🦋 Changeset detected

Latest commit: 00f097f585abaaa11c8a077a49230304f1e3fc8d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages | Name | Type | | ------------------------- | ----- | | @evidence-dev/components | Patch | | @evidence-dev/evidence | Patch | | evidence-test-environment | Patch |

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

vercel[bot] commented 1 year ago

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated
evidence-docs ✅ Ready (Inspect) Visit Preview Aug 31, 2022 at 9:30PM (UTC)
hughess commented 1 year ago

A problem introduced with the 100% limit on the y-axis is an overlap with the y-axis title (if one is applied). I don't have a clear idea of a fix for this yet:

CleanShot 2022-08-23 at 16 17 17@2x
archiewood commented 1 year ago

@hughess I think this is probably the wrong placement for this y axis label anyway. I think a more natural position would be above the y-axis, or on the LHS. Realize this might take a bit of thinking due to title / subtitle position

archiewood commented 1 year ago

Interestingly FT and Economist both put y axis info in the subtitle

(And axis labels on RHS):

image image

NYT also puts y axis title in subtitle position

image
hughess commented 1 year ago

@archiewood those are interesting examples. I agree about considering some other placement.

Given that moving the label would be reasonably time-consuming (because we'll need to test it out across all the chart types/orientations), I'm wondering if we should release the stacked charts despite this issue, or wait to release them until we have the issue solved.

I'm thinking that a stacked % chart would rarely need a y-axis label, so I'm leaning towards releasing the charts now and fixing the label issue later. What do you think?

archiewood commented 1 year ago

I think the only time you would need one would be something a bit descriptive, like "% of total orders" or similar.

I think it's probably fine as you say. If someone really wants to label the y axis, they can use the subtitle.

You could put a note in the docs about it, but might just be confusing.

hughess commented 1 year ago

Another issue with the current approach is that the tooltip values are not able to receive the correct percentage formatting.

CleanShot 2022-08-25 at 09 20 39@2x

This is because all the aggregation logic is located inside of Bar.svelte.

Issues with Aggregations in Primitive Components

Short-term Solution

The simplest solution to this issue for now is to move the aggregation logic from the low-level Bar component into the high-level BarChart component, so the data is transformed before Chart gets called. This should cover most of our use cases for 100% stacked charts, but it also means that the 100% stack will not work in composable charts.

i.e., the below would not work:

<Chart data={sales_data} x=category y=sales>
   <Bar type=stacked100/>
</Chart>

...but this would:

<BarChart data={sales_data} x=category y=sales type=stacked100/>
archiewood commented 1 year ago

I love the stacked chart. Can't wait to use it in my reports.

Thoughts:

  1. Syntax & Errors It seems you need to specify the x and y props for it to work. This is not how the normal stacked bar works:
    <BarChart 
    data={orders_by_category} 
    series=category
    />

    works

But

<BarChart 
    data={orders_by_category} 
    series=category
    type=stacked100
/>

does not. And yields a rather puzzling error:

image
  1. Single bars Agree with your notes in the example-project these don't look great. But this is a more general problem in . Currently I think the best visual result is to swapXY: image

Longer term I agree with some of your ideas. The only one i would add is having it so that the Chart doesn't take up 100% width, though this might have wider implications!

hughess commented 1 year ago

@archiewood thanks! Great catch. That's a bug caused by putting the aggregation in the top-level component - will see how we can get the same prop-filling as the regular stacked bar.

hughess commented 1 year ago

This has uncovered another similar issue - the stacked100 option doesn't work in charts where multiple y columns are supplied (either explicitly or assumed by Chart through it's prop-filling logic).

There are 2 steps to fix this:

  1. Move the stacked chart aggregation logic from the top-level BarChart and AreaChart components into Chart, so we can trigger the aggregation after the props have all been filled in
  2. Change the getStackedPercentages function to allow it to handle multiple y columns and output the appropriate dataset to use in the chart

Step 1 is done. Step 2 I'll tackle tomorrow.

hughess commented 1 year ago

@archiewood this last commit should fix the error you had. Would you mind giving it a quick test when you have a chance, just to make sure?

archiewood commented 1 year ago

Yeah this works as I expected:

Code:

```needful_items
select 
substr(order_datetime,0,7) as order_month,
item,
sum(sales) as sales_usd
from orders
group by 1,2 order by 1

<BarChart data={needful_items} series=item sort=false />

<BarChart data={needful_items} series=item sort=false type=stacked100 />



Result:
<img width="609" alt="image" src="https://user-images.githubusercontent.com/58074498/187786966-5bcdb1be-bef9-40d6-891f-0f7daa73e934.png">
hughess commented 1 year ago

Amazing, thanks!