# Perspective Box and Whisker Plot

**URL:** <https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034>\
**Category:** Ignition Exchange\
**Tags:** ignition80, perspective\
**Created:** [August 24, 2020, 7:01pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034 "2020-08-24T19:01:49Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![nickboratyn](https://avatars.discourse-cdn.com/v4/letter/n/9d8465/32.png) [@nickboratyn](https://forum.inductiveautomation.com/u/nickboratyn)\
**Post date:** [August 24, 2020, 7:01pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/1 "2020-08-24T19:01:49Z")

</div>

I was actually wondering if anyone had or had advice on how to create a box and whisker plot view using ignition perspective.

I have tried using the candlestick render mode but I am still struggling on the data because my box and whisker plot will be temperature values on the y-axis and many temperature variables on the x-axis not time.

Thank you for any input

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [August 24, 2020, 10:11pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/2 "2020-08-24T22:11:40Z")

</div>

Using the candlestick render isn’t going to be exactly the same as a box and whisker plot, but depending on your needs it might get you close enough.

Instead of a time axis, use a category X-axis to organize your temperature variables. Each temperature variable will be it’s own _category_, and will one have one data entry, containing an open, high, low, and close value. Then under _series_, map _candlestick.open_, _candlestick.high_, _candlestick.low_, and _data_ to the corresponding values.

Sidenote:  
I think it might be possible to render something that actually resembles an actual box and whisker plot by playing around with column render widths. If anyone wants get deep in the weeds on this, I’d try making series for:

1. Min Marker
2. Min to Q1
3. Q1 to Median
4. Median Marker
5. Median to Q3
6. Q3 to Max
7. Max Marker

By playing around with the colors and width/heights of the different series I think something serviceable can be made. You’ll probably have to do something wacky in order to give your min, median, and max markers a visible thickness (maybe draw the real value ± some percentage of the chart range?).

---

<div class="post-metadata">

**Author:** ![nickboratyn](https://avatars.discourse-cdn.com/v4/letter/n/9d8465/32.png) [@nickboratyn](https://forum.inductiveautomation.com/u/nickboratyn)\
**Post date:** [August 25, 2020, 3:27pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/3 "2020-08-25T15:27:44Z")

</div>

Thank you for your help,  
Is there anyway you can give an example of what your describing in the first part (not the side note)? I am trying to get that together but my graph is always blank but not in error.

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [August 25, 2020, 4:12pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/4 "2020-08-25T16:12:11Z")

</div>

I couldn’t get the ‘Low’ value of the candlestick to render correctly; maybe someone from IA should take a look at it…

 ![Candlestick](https://us1.discourse-cdn.com/inductiveautomation/original/3X/3/3/33ab0c035773cf3a004882b3efee14e2828b8e7e.png)  
[candlestick.json](https://forum.inductiveautomation.com/uploads/short-url/6he4xJTBluqvpJUjdvesJj7RScE.json) (14.4 KB)

---

<div class="post-metadata">

**Author:** ![nickboratyn](https://avatars.discourse-cdn.com/v4/letter/n/9d8465/32.png) [@nickboratyn](https://forum.inductiveautomation.com/u/nickboratyn)\
**Post date:** [August 25, 2020, 5:54pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/5 "2020-08-25T17:54:04Z")

</div>

I appreciate that a lot. I think that will work or at least get me pointed in the right direction. You’ll have to forgive me, I am very new to perspective. I get an error when I paste the JSON code into my root container. Am I doing something wrong when trying to get that graph imported?  
 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/a/e/ae78c44b30766bf2f32616da648e62307e2b07e7.png)

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/3/f/3fa494231cf71e855d83c11b59008ab0ef1d52bb.png)

---

<div class="post-metadata">

**Author:** ![nickboratyn](https://avatars.discourse-cdn.com/v4/letter/n/9d8465/32.png) [@nickboratyn](https://forum.inductiveautomation.com/u/nickboratyn)\
**Post date:** [August 25, 2020, 7:29pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/6 "2020-08-25T19:29:45Z")

</div>

I was able to get it working as of now, I see what you mean when you say the low is not working as expected. Do you think we are missing a parameter? basically the line should stop at the low value but it just goes straight to zero or the x-axis.

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [August 25, 2020, 8:00pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/7 "2020-08-25T20:00:04Z")

</div>

👍🏻 Glad to hear.

> [@nickboratyn](#):
>
> basically the line should stop at the low value but it just goes straight to zero or the x-axis

That’s exactly what I’m seeing, no amount of fiddling with the data source seem to make any difference. For reference I’m on 8.0.15. Maybe @ynejati can take a look at this.

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [August 25, 2020, 10:08pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/8 "2020-08-25T22:08:52Z")

</div>

Here’s a first draft of a proper box and whisker chart. Can you test this out for me and make sure it renders like you would expect?

It definitely needs some theming options as well as some axis options: what kind of coloring options would you expect to have?

 ![BoxAndWhisker](https://us1.discourse-cdn.com/inductiveautomation/original/3X/4/9/490960bd61ad2073ff687b9221cb62ea4378797a.png) [BoxAndWhisker.zip](https://forum.inductiveautomation.com/uploads/short-url/lKpwZ7idGi2IYEgd4FfDw0FruYX.zip) (16.0 KB)

---

<div class="post-metadata">

**Author:** ![nickboratyn](https://avatars.discourse-cdn.com/v4/letter/n/9d8465/32.png) [@nickboratyn](https://forum.inductiveautomation.com/u/nickboratyn)\
**Post date:** [August 26, 2020, 12:25pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/9 "2020-08-26T12:25:16Z")

</div>

I took a look at it and I like the aesthetic of this box and whisker plot. It does accurately resembles a box and whisker more. I think the hard part will be the way I have to get data into this graph. I have one dataset tag with 17 columns of many values in that dataset as shown below.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/3/9/39c992988c12c15b78a305f2d9971c6677dbbe81.png)

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [August 26, 2020, 12:47pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/10 "2020-08-26T12:47:44Z")

</div>

Is your dataset tag the recorded temperature readings? If so, I’d set up some kind of gateway task to regularly calculate the quartile data for each TC. You could store these calculation results in a separate dataset tag (or maybe a document tag?).

Then on the Box and Whisker chart, bind the _props.data_ property to your calculated values tag and apply any script transforms needed to create the objects that the chart expects.

---

<div class="post-metadata">

**Author:** ![nickboratyn](https://avatars.discourse-cdn.com/v4/letter/n/9d8465/32.png) [@nickboratyn](https://forum.inductiveautomation.com/u/nickboratyn)\
**Post date:** [August 26, 2020, 6:20pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/11 "2020-08-26T18:20:12Z")

</div>

So far I have tagged the min, max and median markers. As you can see its not quite right and I tried to work with the values to get the box to match up to the markers but nothing I was doing seems to work well. Do I need to figure out the max of the median and the median of the max for example to make the graph look better?

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/a/e/aef1f68d0ee9a1208343bfc083bb24f9aaf9aed1.png)

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [August 26, 2020, 9:19pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/12 "2020-08-26T21:19:31Z")

</div>

You need to use the parameters on the embedded view in the _Example_ window, and not touch anything inside of the view named _Template_. There’s some scripting happening to get everything to render properly. See the picture I posted above for a reference.

---

<div class="post-metadata">

**Author:** ![nickboratyn](https://avatars.discourse-cdn.com/v4/letter/n/9d8465/32.png) [@nickboratyn](https://forum.inductiveautomation.com/u/nickboratyn)\
**Post date:** [August 27, 2020, 1:49pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/13 "2020-08-27T13:49:46Z")

</div>

![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/4/4/44e310f27528b70734240b5379f20a28c1f3d712.png)  
I have to apologize, when you said data I figured you meant the datasource elements. But yes, when I tagged the data in the proper place the graph looks really great. I can’t thank you enough for the help. the last small question I have is for the values of q1 and q3, that would technically but the high and low of the median value right? What expression do you usually use for grabbing that data?  
EDIT: I am taking the standard deviation and adding to the median for my Q3 value and subtracting it from the median for my Q1 value.

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [August 27, 2020, 11:13pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/14 "2020-08-27T23:13:00Z")

</div>

Great, I’m glad you were able to get it working!

Q1 and Q3 refer to quartile 1 and quartile 3, which are the **median** of the lower half of the data set and the **median** of the upper half of the data set respectively.

First calculate the **median** of your dataset. Then, group all the values less than the **median** and group all the values greater than the **median**. Taking the **median** of the lower set will give you Q1 and taking the **median** of the upper set will give you Q3.

Graphing **median ± SD** is probably not very useful; it’s possible for the **median + SD** to be greater than the maximum sampled value.

Edit: misused mean instead of median.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [August 27, 2020, 11:24pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/15 "2020-08-27T23:24:08Z")

</div>

This is not a correct description of quartiles. Q2 is the _ **median** _ of the entire dataset. Q1 is the _ **median** _ of the lower half (not below the mean, below the median). Q3 is the _ **median** _ of the upper half.

(Even that description is a bit fuzzy, as it doesn’t address what to do when the number of samples doesn’t divide up neatly.)

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [August 27, 2020, 11:42pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/16 "2020-08-27T23:42:18Z")

</div>

> [@pturmel](#):
>
> This is not a correct description of quartiles. Q2 is the _ **median** _ of the entire dataset. Q1 is the _ **median** _ of the lower half (not below the mean, below the median). Q3 is the _ **median** _ of the upper half.

Oops, you’re absolutely right. Mean is incorrect, median is what you need.

The point still stands about _median +- SD_ though.

---

<div class="post-metadata">

**Author:** ![nickboratyn](https://avatars.discourse-cdn.com/v4/letter/n/9d8465/32.png) [@nickboratyn](https://forum.inductiveautomation.com/u/nickboratyn)\
**Post date:** [August 28, 2020, 1:11pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/17 "2020-08-28T13:11:15Z")

</div>

I get what I have to do: Split the dataset by taking the median, then taking the median again of the upper half and lower half from the original median that was taken. I am struggling on how to do that through an expression binding. Any input on that would be appreciated

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [August 28, 2020, 2:03pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/18 "2020-08-28T14:03:00Z")

</div>

> [@nickboratyn](#):
>
> am struggling on how to do that

Don't split the dataset. Just make a list of all the values, and sort it. Take the subscript of the last value (length - 1) and multiply it by ¼, ½, and ¾. Where those are integers, that is the subscript of the value for that quartile. If there's a fraction, round down and up for your subscripts, and interpolate between those values.

( Use a script transform. )

---

<div class="post-metadata">

**Author:** ![nickboratyn](https://avatars.discourse-cdn.com/v4/letter/n/9d8465/32.png) [@nickboratyn](https://forum.inductiveautomation.com/u/nickboratyn)\
**Post date:** [August 28, 2020, 7:21pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/19 "2020-08-28T19:21:48Z")

</div>

So I have the dataset sorted in ascending order. When you say take a subscript of the last value (length -1). I am not quite sure want you mean there.

---

<div class="post-metadata">

**Author:** ![dkhayes117](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/dkhayes117/32/68344_2.png) [@dkhayes117](https://forum.inductiveautomation.com/u/dkhayes117)\
**Post date:** [August 28, 2020, 7:35pm UTC](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034/20 "2020-08-28T19:35:39Z")

</div>

I think he means the index value. Once you have a list of all your values, find the length and minus 1 then get your indexes for the quartiles like below

```auto
myList = (1,2,4,5,7,8,9,12,13,13,14)
nodeCnt = len(myList) - 1
q1_ndx = nodeCnt * .25
q2_ndx = nodeCnt * .5
q3_ndx = nodeCnt * .75

print q1_ndx, q2_ndx, q3_ndx #Result is 2.75, 5.5, and 8.25

```

Once you have these values, if it is a fraction, round up and round down to get the index values needed to average the actual values. For example, for q1 in my script, the index value is 2.75. There is no 2.75 index, so round up and down to get 2 and 3. Quartile 1 will be the average of indexes 2 and 3

```auto
q1 = (myList[2]+myList[3]/2)

```

**EDIT**  
An easier way is to use `system.math.percentile()`

```auto
myList = (1,2,4,5,7,8,9,12,13,13,14)
q1 = system.math.percentile(myList,25)
q2 = system.math.percentile(myList,50)
q3 = system.math.percentile(myList,75)

```

[Next page](https://forum.inductiveautomation.com/t/perspective-box-and-whisker-plot/38034.md?page=2)
