2018-11-25 21:53:26 +08:00
|
|
|
/*
|
2024-02-06 21:50:49 +08:00
|
|
|
Copyright (c) 2008-2024 Jan W. Krieger (<jan@jkrieger.de>)
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This software is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU Lesser General Public License (LGPL) as published by
|
2019-02-08 00:24:46 +08:00
|
|
|
the Free Software Foundation, either version 2.1 of the License, or
|
2018-11-25 21:53:26 +08:00
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU Lesser General Public License (LGPL) for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public License (LGPL)
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2022-04-25 04:07:39 +08:00
|
|
|
#ifndef jkqtpgraphsboxplot_H
|
|
|
|
#define jkqtpgraphsboxplot_H
|
|
|
|
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
#include <QString>
|
|
|
|
#include <QPainter>
|
|
|
|
#include <QPair>
|
2019-05-30 04:40:02 +08:00
|
|
|
#include "jkqtplotter/jkqtptools.h"
|
2019-06-22 20:21:32 +08:00
|
|
|
#include "jkqtplotter/jkqtplotter_imexport.h"
|
2019-05-30 04:40:02 +08:00
|
|
|
#include "jkqtplotter/jkqtpimagetools.h"
|
2018-12-19 00:13:18 +08:00
|
|
|
#include "jkqtplotter/jkqtpgraphsbase.h"
|
2020-09-21 19:40:38 +08:00
|
|
|
#include "jkqtplotter/graphs/jkqtpboxplotbase.h"
|
2019-06-20 22:06:31 +08:00
|
|
|
#include "jkqtplotter/graphs/jkqtpboxplotstylingmixins.h"
|
2019-04-22 23:19:52 +08:00
|
|
|
#include "jkqtplotter/jkqtpgraphsbasestylingmixins.h"
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-04-22 23:19:52 +08:00
|
|
|
|
2019-05-11 21:56:11 +08:00
|
|
|
/*! \brief This implements vertical <a href="http://en.wikipedia.org/wiki/Box_plot">boxplots</a>, optionally also a notched boxplot
|
2019-01-13 01:53:16 +08:00
|
|
|
\ingroup jkqtplotter_statgraphs
|
2018-11-25 21:53:26 +08:00
|
|
|
|
2019-01-20 23:15:10 +08:00
|
|
|
The x position is given in posColumn. All other data are given in the medianColumn, minColumn, maxColumn,
|
2018-11-25 21:53:26 +08:00
|
|
|
percentile25Column and percentile75Column.
|
|
|
|
|
2022-09-27 05:16:28 +08:00
|
|
|
\image html JKQTPBoxplotVerticalGraph.png
|
2019-01-20 23:15:10 +08:00
|
|
|
|
2019-05-11 21:56:11 +08:00
|
|
|
|
2019-01-20 23:15:10 +08:00
|
|
|
The different features of a boxplot are:
|
|
|
|
|
2019-05-11 21:56:11 +08:00
|
|
|
\image html plot_boxplotverticalelement.png
|
|
|
|
|
|
|
|
|
|
|
|
The example \ref JKQTPlotterBoxplotStyling discusses different options to style boxplots:
|
|
|
|
|
|
|
|
\image html test_styledboxplot.png
|
2019-01-20 23:15:10 +08:00
|
|
|
|
2019-05-06 01:31:20 +08:00
|
|
|
This class also implements hitTest() in a way that displays all data of the boxplot in the tooltips:
|
|
|
|
|
|
|
|
\image html tooltip_boxplot.png
|
|
|
|
|
2019-01-20 23:15:10 +08:00
|
|
|
\note There are additional classes to draw a single boxplot element: JKQTPBoxplotHorizontalElement and JKQTPBoxplotVerticalElement.
|
|
|
|
In these you can set the data values, as they are NOT drawn from a data column. This can be useful, if you e.g. want to
|
|
|
|
draw the statistical properties of a distribution.
|
|
|
|
|
|
|
|
\section BoxplotOutliers Outliers
|
|
|
|
|
|
|
|
If you also want to display outliers, as shown here with circles:
|
|
|
|
|
|
|
|
\image html boxplot_outliers.png
|
|
|
|
|
|
|
|
You need to add them as (x,y)-pairs to the datastore and add a separate JKQTPXYLineGraph that shows these. See \ref JKQTPlotterBoxplotsGraphs for details. Here is an example code-snippet:
|
|
|
|
|
|
|
|
\code
|
|
|
|
// 4. create a graph of vertical boxplots:
|
|
|
|
JKQTPBoxplotVerticalGraph* graph=new JKQTPBoxplotVerticalGraph(&plot);
|
2019-04-22 23:19:52 +08:00
|
|
|
graph->setPositionColumn(columnPOS);
|
2019-01-26 20:00:40 +08:00
|
|
|
graph->setMinColumn(columnMIN);
|
|
|
|
graph->setPercentile25Column(columnQ25);
|
|
|
|
graph->setMedianColumn(columnMEDIAN);
|
|
|
|
graph->setMeanColumn(columnMEAN);
|
|
|
|
graph->setPercentile75Column(columnQ75);
|
|
|
|
graph->setMaxColumn(columnMAX);
|
|
|
|
graph->setTitle("vertical Boxplots");
|
2019-01-20 23:15:10 +08:00
|
|
|
|
|
|
|
// 5. outliers need to be drawn separately
|
|
|
|
JKQTPXYLineGraph* graphOutliers=new JKQTPXYLineGraph(&plot);
|
2019-01-26 20:00:40 +08:00
|
|
|
graphOutliers->setXColumn(columnOUTLIERSX);
|
|
|
|
graphOutliers->setYColumn(columnOUTLIERSY);
|
|
|
|
graphOutliers->setTitle("outliers");
|
2019-01-20 23:15:10 +08:00
|
|
|
// make the color a darker shade of the color of graph
|
2019-01-26 20:00:40 +08:00
|
|
|
graphOutliers->setColor(graph->getColor().darker());
|
|
|
|
graphOutliers->setFillColor(QColor("white"));
|
2019-01-20 23:15:10 +08:00
|
|
|
// draw outliers as small circles, without lines
|
2019-04-22 19:27:50 +08:00
|
|
|
graphOutliers->setSymbolType(JKQTPCircle);
|
2019-01-26 20:00:40 +08:00
|
|
|
graphOutliers->setDrawLine(false);
|
|
|
|
graphOutliers->setSymbolSize(7);
|
2019-01-20 23:15:10 +08:00
|
|
|
\endcode
|
|
|
|
|
2019-06-13 16:27:06 +08:00
|
|
|
\see \ref JKQTPlotterBoxplotsGraphs, jkqtpstatVAddBoxplots(),\ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat, \ref JKQTPlotterBasicJKQTPDatastoreStatistics, \ref JKQTPlotterBoxplotStyling
|
2019-01-20 23:15:10 +08:00
|
|
|
|
2018-11-25 21:53:26 +08:00
|
|
|
*/
|
2020-09-21 19:40:38 +08:00
|
|
|
class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotVerticalGraph: public JKQTPBoxplotGraphBase {
|
2018-11-25 21:53:26 +08:00
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
|
|
/** \brief class constructor */
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPBoxplotVerticalGraph(JKQTBasePlotter* parent=nullptr);
|
2018-11-25 21:53:26 +08:00
|
|
|
/** \brief class constructor */
|
2019-01-20 23:15:10 +08:00
|
|
|
JKQTPBoxplotVerticalGraph(JKQTPlotter* parent);
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
/** \brief plots the graph to the plotter object specified as parent */
|
2019-04-22 23:19:52 +08:00
|
|
|
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
2018-11-25 21:53:26 +08:00
|
|
|
/** \brief plots a key marker inside the specified rectangle \a rect */
|
2023-12-19 05:24:59 +08:00
|
|
|
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, const QRectF& rect) override;
|
2018-11-25 21:53:26 +08:00
|
|
|
|
2024-02-05 05:06:09 +08:00
|
|
|
/** \copydoc JKQTPPlotElement::getXMinMax() */
|
2018-12-28 05:52:00 +08:00
|
|
|
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) override;
|
2024-02-05 05:06:09 +08:00
|
|
|
/** \copydoc JKQTPPlotElement::getYMinMax() */
|
2018-12-28 05:52:00 +08:00
|
|
|
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override;
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-05-11 21:56:11 +08:00
|
|
|
/*! \brief This implements horizontal <a href="http://en.wikipedia.org/wiki/Box_plot">boxplots</a>, optionally also a notched boxplot
|
2019-01-13 01:53:16 +08:00
|
|
|
\ingroup jkqtplotter_statgraphs
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
the x position is given in posColumn. All other data are given in the medianColumn, minColumn, maxColumn,
|
|
|
|
percentile25Column and percentile75Column.
|
|
|
|
|
2022-09-27 05:16:28 +08:00
|
|
|
\image html JKQTPBoxplotHorizontalGraph.png
|
2019-01-20 23:15:10 +08:00
|
|
|
|
|
|
|
\note See the documentation of JKQTPBoxplotVerticalGraph for details on the properties of this class!
|
|
|
|
|
2019-06-13 16:27:06 +08:00
|
|
|
\see JKQTPBoxplotVerticalGraph \ref JKQTPlotterBoxplotsGraphs, jkqtpstatHAddBoxplots(), \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat, \ref JKQTPlotterBasicJKQTPDatastoreStatistics, \ref JKQTPlotterBoxplotStyling
|
2019-01-20 23:15:10 +08:00
|
|
|
|
2018-11-25 21:53:26 +08:00
|
|
|
*/
|
2020-09-21 19:40:38 +08:00
|
|
|
class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotHorizontalGraph: public JKQTPBoxplotGraphBase {
|
2018-11-25 21:53:26 +08:00
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
/** \brief class constructor */
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPBoxplotHorizontalGraph(JKQTBasePlotter* parent=nullptr);
|
2019-01-20 23:15:10 +08:00
|
|
|
JKQTPBoxplotHorizontalGraph(JKQTPlotter* parent);
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
/** \brief plots the graph to the plotter object specified as parent */
|
2018-12-28 05:52:00 +08:00
|
|
|
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
2018-11-25 21:53:26 +08:00
|
|
|
/** \brief plots a key marker inside the specified rectangle \a rect */
|
2023-12-19 05:24:59 +08:00
|
|
|
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, const QRectF& rect) override;
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
|
2024-02-05 05:06:09 +08:00
|
|
|
/** \copydoc JKQTPPlotElement::getXMinMax() */
|
2018-12-28 05:52:00 +08:00
|
|
|
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) override;
|
2024-02-05 05:06:09 +08:00
|
|
|
/** \copydoc JKQTPPlotElement::getYMinMax() */
|
2018-12-28 05:52:00 +08:00
|
|
|
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override;
|
2018-11-25 21:53:26 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-05-11 21:56:11 +08:00
|
|
|
/*! \brief This implements a single vertical <a href="http://en.wikipedia.org/wiki/Box_plot">(notched) boxplot</a> as a "geometric element",
|
2019-01-20 23:15:10 +08:00
|
|
|
where the data is directly given to the object and not stored in a column, as in JKQTPBoxplotVerticalGraph
|
2019-01-13 01:53:16 +08:00
|
|
|
\ingroup jkqtplotter_statgraphs
|
2022-10-23 03:07:14 +08:00
|
|
|
\ingroup jkqtplotter_statgraphs
|
2018-11-25 21:53:26 +08:00
|
|
|
|
2019-01-20 23:15:10 +08:00
|
|
|
|
|
|
|
|
2018-11-25 21:53:26 +08:00
|
|
|
the x position is given in posColumn. All other data are given in the median, min, max,
|
|
|
|
percentile25 and percentile75.
|
|
|
|
|
2019-01-20 23:15:10 +08:00
|
|
|
The different features of a boxplot are:
|
|
|
|
|
2019-05-11 21:56:11 +08:00
|
|
|
\image html plot_boxplotverticalelement.png
|
|
|
|
|
|
|
|
|
|
|
|
The example \ref JKQTPlotterBoxplotStyling discusses different options to style boxplots:
|
|
|
|
|
|
|
|
\image html test_styledboxplot.png
|
|
|
|
|
2019-06-13 16:27:06 +08:00
|
|
|
\see jkqtpstatVAddBoxplot(), \ref JKQTPlotterBasicJKQTPDatastoreStatistics, \ref JKQTPlotterBoxplotsGraphs, \ref JKQTPlotterBoxplotStyling, jkqtpstatAddVBoxplotAndOutliers()
|
|
|
|
|
2018-11-25 21:53:26 +08:00
|
|
|
*/
|
2020-09-21 19:40:38 +08:00
|
|
|
class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotVerticalElement: public JKQTPBoxplotElementBase {
|
2018-11-25 21:53:26 +08:00
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
/** \brief class constructor */
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPBoxplotVerticalElement(JKQTBasePlotter* parent=nullptr);
|
2018-11-25 21:53:26 +08:00
|
|
|
/** \brief class constructor */
|
2019-01-20 23:15:10 +08:00
|
|
|
JKQTPBoxplotVerticalElement(JKQTPlotter* parent);
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
/** \brief plots the graph to the plotter object specified as parent */
|
2018-12-28 05:52:00 +08:00
|
|
|
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
2018-11-25 21:53:26 +08:00
|
|
|
/** \brief plots a key marker inside the specified rectangle \a rect */
|
2023-12-19 05:24:59 +08:00
|
|
|
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, const QRectF& rect) override;
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
|
2024-02-05 05:06:09 +08:00
|
|
|
/** \copydoc JKQTPPlotElement::getXMinMax() */
|
2018-12-28 05:52:00 +08:00
|
|
|
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) override;
|
2024-02-05 05:06:09 +08:00
|
|
|
/** \copydoc JKQTPPlotElement::getYMinMax() */
|
2018-12-28 05:52:00 +08:00
|
|
|
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override;
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
2020-09-21 19:40:38 +08:00
|
|
|
|
2018-11-25 21:53:26 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2019-05-11 21:56:11 +08:00
|
|
|
/*! \brief This implements a horizontal <a href="http://en.wikipedia.org/wiki/Box_plot">(notched) boxplot</a> where the data is directly given to the
|
2019-01-20 17:49:29 +08:00
|
|
|
object and not stored in a column, as in JKQTPBoxplotVerticalGraph
|
2019-01-13 01:53:16 +08:00
|
|
|
\ingroup jkqtplotter_statgraphs
|
2022-10-23 03:07:14 +08:00
|
|
|
\ingroup jkqtplotter_statgraphs
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
the x position is given in pos. All other data are given in the median, min, max,
|
|
|
|
percentile25 and percentile75.
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
\image html plot_boxplothorizontalelement.png
|
2019-01-20 23:15:10 +08:00
|
|
|
|
|
|
|
\note See JKQTPBoxplotVerticalElement for a detailed documentation
|
|
|
|
|
2019-06-13 16:27:06 +08:00
|
|
|
\see JKQTPBoxplotVerticalElement, jkqtpstatHAddBoxplot(), \ref JKQTPlotterBasicJKQTPDatastoreStatistics, \ref JKQTPlotterBoxplotsGraphs, \ref JKQTPlotterBoxplotStyling, jkqtpstatAddHBoxplotAndOutliers()
|
|
|
|
|
2018-11-25 21:53:26 +08:00
|
|
|
*/
|
2020-09-21 19:40:38 +08:00
|
|
|
class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotHorizontalElement: public JKQTPBoxplotElementBase {
|
2018-11-25 21:53:26 +08:00
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
/** \brief class constructor */
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPBoxplotHorizontalElement(JKQTBasePlotter* parent=nullptr);
|
2018-11-25 21:53:26 +08:00
|
|
|
/** \brief class constructor */
|
2019-01-20 23:15:10 +08:00
|
|
|
JKQTPBoxplotHorizontalElement(JKQTPlotter* parent);
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
/** \brief plots the graph to the plotter object specified as parent */
|
2018-12-28 05:52:00 +08:00
|
|
|
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
2018-11-25 21:53:26 +08:00
|
|
|
/** \brief plots a key marker inside the specified rectangle \a rect */
|
2023-12-19 05:24:59 +08:00
|
|
|
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, const QRectF& rect) override;
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
|
2024-02-05 05:06:09 +08:00
|
|
|
/** \copydoc JKQTPPlotElement::getXMinMax() */
|
2018-12-28 05:52:00 +08:00
|
|
|
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) override;
|
2024-02-05 05:06:09 +08:00
|
|
|
/** \copydoc JKQTPPlotElement::getYMinMax() */
|
2018-12-28 05:52:00 +08:00
|
|
|
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override;
|
2018-11-25 21:53:26 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-12-19 00:13:18 +08:00
|
|
|
#endif // jkqtpgraphsboxplot_H
|