Creating Box-and_Whisker plots

Hello,

I want to display my data by using a Box-Whisker plot. However, I couldn't find a way of calculating and plotting 3 different waves on one graph. When I use the Windows-->New-->Box Plot, it is fine. However, when I want to write a procedure for that I can't show the data on one plot. I use the following codes:

fWavePercentile("F1_W", "10;25;50;75;90", "P_F1", 0, 0, 0) // Calculate the percentiles for first wave
fWavePercentile("F2_W", "10;25;50;75;90", "P_F2", 0, 0, 0) // Do the same for the second wave
fWavePercentile("F3_W", "10;25;50;75;90", "P_F3", 0, 0, 0) // Same for the third wave

then;

fBoxPlot(P_F1_50, P_F1_75, P_F1_25, P_F1_90, P_F1_10, $"", 0.3, 0, $"", $"", 0, 0, 0) // Plot the first values

I don't know how to append the others and also how to modify the appearance of the final plot. Any suggestions?

Thank you so much,
Emre
Unfortunately, that routine wasn't designed with multiple box plots in a single graph in mind. Making the whole, complicated thing accommodate that would be pretty complicated.

I was able, with a great deal of effort, to append a new box plot to one I had already made. Here's what I did:

0) I used a text wave as the X wave so that the box plot is a category plot. I don't think it will be easy to do it any other way.

1) I copied the code for the fBoxPlot function to the main procedure window. I renamed the function fAppendBoxPlot and changed "Display" to "AppendToGraph" somewhere around the middle of the function.

2) I made a second independent box plot, being careful to use a different name for the result waves. You have already done that by invoking fWavePercentile with different strings in the first parameter.

3) You will need to make the starting plot using fBoxPlot; I did that just by using the control panel to make the first plot;

4) Use the fAppendBoxPlot function with the starting plot as the top graph. Use the command you use above substituting fAppendBoxPlot for fBoxPlot and "P_F2" for "P_F1" and then again with "P_F3".

5) You now have something of a mess... Double-click any trace to bring up the Modify Trace Appearance dialog.

5a) Find the last trace of the first box plot. Since you aren't using outliers, that would be P_F1_25. Change the Grouping mode to None. Do it for the P_F2_25 trace also. This will make the boxes occupy different slots in the category bar space.

5b) The boxes and median lines are actually X error bars. One by one, select the median traces (P_Fn_50), un-check and re-check the Error Bars checkbox to bring up the Error Bars dialog. Change the X +/- setting to something narrower. Since you will have three boxes, you might choose something like .15. I'm not sure- you will have to experiment.

By now you should have a box plot with three data sets. Since the Graph->Modify Box Plot control panel doesn't expect the extra traces, etc., you can't use it to modify the appearance of the plot. You can use the Modify Trace Appearance dialog to change line thickness and trace color.

Unfortunately, filling the boxes on a box plot is done by adding colored rectangles as drawing objects. It is a royal pain in the neck (or other body part) to do it manually, and the box plot code won't do it correctly in this case. Probably you will have to do without. Maybe you could add colored fills to the error boxes in a drawing program if you export the graph in a suitable format.

I have attached a PNG of the graph I made.

I'm sorry this is so difficult. I will add the capability to my list of things I need to do. Unfortunately, the list is long and dominated by our extensive re-write of Igor for version 7.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
Hello,

Thank you so much for your great effort. I can maybe change my question and modify the input that I use, so I won't have to work each data set separately. My new question: What if I have three time series on one graph and analyze them together. I can do it by using the control panel but couldn't find how to do it writing a procedure. I attached one example that I made by using control panel. The main problem is, I don't see any commands on the command window when I use the control panel.

Cheers,
Emre

Hello,

Thank you so much for your help. Unfortunately, I can't send you a copy of the file becuase it is confusing and I am trying to make it clear. Anyway, thank you so much. I'd better use the control panel for this part.

Best,
Emre
It's probably a bit late, but I encountered the same issue lately. One practical way could be to manually build the boxplot as long as you have the percentile data (let's say 10, 25, 50, 75 and 90).
then:
- make a category plot of all percentiles
- p10 should be: Marker "-"/ no grouping / black
- p25 should be: sticks to next/ Draw to next / black
- p50 should be: Bar to next / Draw to next / colored
- p75 should be: Bar to next / Draw to next / colored
- p90 should be: stick and marker "-" / Draw to next / black

if needed, reorder the traces (10-25-50-75-90)

this way, I have been able to build the enclosed graph.
I haven't written a procedure to do it automatically, but I guess it is rather simple. Although I used the boxplot package to calculate all the percentiles, I guess it is possible to implement this in a function.

hope this helps someone.
J-E
J-E Petit- your manual process is almost what the Box Plot procedure file does. You are clearly an Igor power user!

The Box Plot procedure uses XY error bars to make the box; that's why they are difficult to fill.

John Weeks
WaveMetrics, Inc.
support@wavemetrics.com
Here is a simple box and whisker plotter I wrote up.

Load new data into the data folder.

Select the the ones you want and hit box. The labels button allows you to change the text of the label.

Enjoy.
Box It.pxp
johnweeks wrote:

The Box Plot procedure uses XY error bars to make the box; that's why they are difficult to fill.


So is there any chance to see in a near future the possibility to fill box plots directly from the panel? :)

Not vital, but from this manual process, I didn't find the solution to append the average value as a marker...
I wrote some functions to do this manual process automatically on a list of waves to plot.

#include <Percentile and Box Plot>

//-------------------------

Function GlobCatBoxPlot(ListOfMx,ListOfPercentiles,XaxisCatPlot)
    wave/S ListofMx,XaxisCatPlot
    string ListOfPercentiles
   
    variable i
    variable rows=dimsize(ListOfMx,0)
    variable nbCat=dimsize(XaxisCatPlot,0)
    Make/O/N=(nbCat) NaNWave
    NaNWave=NaN
    display
    AppendToGraph NaNWave vs XaxisCatPlot
    for (i=0;i<rows;i+=1)
        GraphOneVariable($ListofMx[i],ListOfPercentiles,XaxisCatPlot)
    endfor
    AppendToGraph NaNWave vs XaxisCatPlot
End Function

//-------------------------

Function CalcMxPerc(Mx,ListOfPercentiles)
    wave Mx
    string ListOfPercentiles
   
    fWavePercentile(NameOfWave(Mx), ListOfPercentiles, NameOfWave(Mx)+"_p", 0,  0, 0)
   
    wave TempSort,TempMatrix,TmpPercentiles,PCNames
    killwaves TempSort,TempMatrix,TmpPercentiles
    string temp_str
    temp_str=NameOfWave(Mx)+"PCNames"
    Rename PCNames $temp_str
    temp_str=NameOfWave(Mx)+"_p_N"
    killwaves $temp_str
End Function

//-------------------------

Function GraphOneVariable(Mx,ListOfPercentiles,XaxisCatPlot)
    wave Mx
    string ListOfPercentiles
    wave/S XaxisCatPlot
   
    CalcMxPerc(Mx,ListOfPercentiles)
   
    string LowWhiskerW_str=NameOfWave(Mx)+"_p_"+StringFromList(0,ListOfPercentiles)
    wave LowWhiskerW=$LowWhiskerW_str
   
    string LowBoxW_str=NameOfWave(Mx)+"_p_"+StringFromList(1,ListOfPercentiles)
    wave LowBoxW=$LowBoxW_str
   
    string MedianW_str=NameOfWave(Mx)+"_p_"+StringFromList(2,ListOfPercentiles)    
    wave MedianW=$MedianW_str
   
    string HighBoxW_str=NameOfWave(Mx)+"_p_"+StringFromList(3,ListOfPercentiles)
    wave HighBoxW=$HighBoxW_str
   
    string HighWhiskerW_str=NameOfWave(Mx)+"_p_"+StringFromList(4,ListOfPercentiles)    
    wave HighWhiskerW=$HighWhiskerW_str
   
    AppendToGraph HighWhiskerW, HighBoxW, MedianW,LowBoxW, LowWhiskerW vs XaxisCatPlot
   
    ModifyGraph mode($LowWhiskerW_str)=3,marker($LowWhiskerW_str)=9,rgb($LowWhiskerW_str)=(0,0,0)
    ModifyGraph mode($LowBoxW_str)=1,toMode($LowBoxW_str)=1,rgb($LowBoxW_str)=(0,0,0)
    ModifyGraph hbFill($MedianW_str)=2,toMode($MedianW_str)=1,useBarStrokeRGB($MedianW_str)=1
    ModifyGraph hbFill($HighBoxW_str)=2,toMode($HighBoxW_str)=1,useBarStrokeRGB($HighBoxW_str)=1
    ModifyGraph mode($HighWhiskerW_str)=8,marker($HighWhiskerW_str)=9,toMode($HighWhiskerW_str)=1, rgb($HighWhiskerW_str)=(0,0,0)
   
End Function


it necessarily uses 5 percentiles to build the boxplot... maybe it'd help
johnweeks wrote:


1) I copied the code for the fBoxPlot function to the main procedure window. I renamed the function fAppendBoxPlot and changed "Display" to "AppendToGraph" somewhere around the middle of the function.



I always encounter 'got 's_name' instead of a string variable or string function name' error when try to compile the fAppendBoxPlot function after changing 'Display' to 'AppendToGraph'. What could be the problem? Thank you!