sgratzl / chartjs-chart-boxplot

Chart.js Box Plots and Violin Plot Charts
https://www.sgratzl.com/chartjs-chart-boxplot/
MIT License
107 stars 24 forks source link

Structure for using precomputed data in boxplot chart via props. #32

Closed LovelyAndy closed 2 years ago

LovelyAndy commented 2 years ago

So I saw this post and I was wondering how the structure in your attached linked works.

I have a pretty weird data structure coming from my backend and I'm not exactly sure how to slot all of that data in the structure you have.

So I have an array with a bunch of objects, each object looks like this :

data: {
            "plot_info": {
                "max": "40",
                "median": "20",
                "min": "0",
                "plot_type": "box_plot",
                "q1": "15",
                "q3": "25",
                "unit": "Mpa"
            },
            "value": {
                "real_value": [ '22', '22', '22', '20', '10', '38', '28', '12', '34', '11', '27' ], // This continues with a total of lets say 100 numbers
                "status": "warning"
            },
            "anomaly_data": {
                "pt1": {
                    "status": "abnormal",
                    "time": "05/23/2022 15:50:00",
                    "value": 45
                },
                "pt2": {
                    "status": "warning",
                    "time": "05/23/2022 15:51:00",
                    "value": -1
                }
            },
        },

So all 3 of these objects are going to help me build out my boxplot chart. First, the plot_info is all of the boxplot data that the backend provides me, like the question linked from early March; there are some bits of data we don't need (plot_type and unit). Second, the value.real_value is all of the values in an array (status doesn't matter here). Finally, anomaly_data.value is our outliers.

I am a bit lost on how to get this data to actually filter into the boxplot chart properly using the format you linked in the previous question:

data: [
              [1, 2, 3, 4, 5],
              {
                min: 1,
                q1: 2,
                median: 3,
                q3: 4,
                max: 5,
              },
              {
                min: 1,
                q1: 2,
                median: 3,
                q3: 4,
                max: 5,
                items: [1, 2, 3, 4, 5],
              },
              {
                min: 1,
                q1: 2,
                median: 3,
                q3: 4,
                max: 5,
                outliers: [1, 2, 3, 4, 5],
              },
            ],

This is all in one dataset, yet there are 3 objs with min, q1, median, q3, max, items; some of which have items, outliers or nothing at all. I figured the first array of [1, 2, 3, 4, 5] would be my value.real_value, but now I'm not so sure.

Context

This is in a vue3 project, but using largely JS for boxplot charts.

Additional context

I made a Codesandbox for this example and am trying to work with it, but so far, no luck. Any ideas or advice would be greatly appreciated. Again, thank you for all your help so far and I look forward to hearing back soon!

sgratzl commented 2 years ago

the example shows different variants to show four boxplots. Each of the variants will show a boxplot.

I played a bit with your code sandbox: https://codesandbox.io/s/boxplot-chartjs-vue-3-with-specific-datastructure-forked-lqlgpb?file=/src/components/BoxPlotChart.vue

LovelyAndy commented 2 years ago

This is great! I didn't expect you to edit the codesandbox, but thank you so much for that! I see there was some trouble with the tooltip, btu that's okay, I can figure that out!

I have a couple clarification questions if you don't mind:

  1. Why are two boxplots rendering, but the outliers are only on one of them? I've been messing around with this codesandbox for a little bit and I can't really tell why there would be two charts.

  2. For both min and max why do you use this syntax?

    max: Math.max(
                Number(props.data.plot_info.max)
                Number(props.data.anomaly_data.pt1.value),
                Number(props.data.anomaly_data.pt2.value)
              ),

    I see that if I take out the pt1 and pt2 lines, the chart get cut off at the top and bottom, but other than that, it stays the same I believe. Are the min and max values from the data not enough there? Doesn't putting the outlier pt1 and pt2 values in there mess with min and max? Just unsure of the purpose for all three values in min and max.

But seriously though, this library has been a huge help to me and your quick responses are much appreciated! Thank you so much!

sgratzl commented 2 years ago
  1. Why are two boxplots rendering, but the outliers are only on one of them? I've been messing around with this codesandbox for a little bit and I can't really tell why there would be two charts.

you configured two, the first one was the raw values, the second the given boxplot values. I just added to "something", "something else" that you can see both.

max: Math.max( Number(props.data.plot_info.max) Number(props.data.anomaly_data.pt1.value), Number(props.data.anomaly_data.pt2.value) ),

didn't seem like that "max" is really the maximum value considering the outliers. As you mentioned, the effect is that the scale doesn't go till the outliers.

LovelyAndy commented 2 years ago

Ahhhh, yeah. So I talked with my backend dev and he was saying that the real_value is all of the data points that they have and that they're doing the conversion on the backend themselves; even though your library does the conversions as well. Thanks for that heads up!

The data that I am working with is just dummy data apparently and even I wondered why they seemed so off.

Either way, this has been a massive help for me. I wish I would've asked you sooner about these boxplots because you taught me more about them in my last post and this one than any of the engineers I work with 😅

Thanks again for the quick and brilliant responses and the wonderful library!