diff --git a/doc/dox/jkqtplotter.dox b/doc/dox/jkqtplotter.dox index f4ea364b2e..eea6936ecc 100644 --- a/doc/dox/jkqtplotter.dox +++ b/doc/dox/jkqtplotter.dox @@ -378,7 +378,7 @@ This group assembles graphs that show their data with symbols and optionally wit \image html jkqtplotter_simpletest_boxplot_small.png JKQTPBoxplotVerticalGraph, JKQTPBoxplotHorizontalGraph - \image html JKQTPViolinplotVerticalElement.png + \image html JKQTPViolinplotVerticalElement_small.png JKQTPViolinplotVerticalElement, JKQTPViolinplotHorizontalElement @@ -422,7 +422,7 @@ This group assembles graphs that show their data with symbols and optionally wit \image html geo_boxplot_small.png JKQTPBoxplotVerticalElement, JKQTPBoxplotHorizontalElement - \image html JKQTPViolinplotVerticalElement.png + \image html JKQTPViolinplotVerticalElement_small.png JKQTPViolinplotVerticalElement, JKQTPViolinplotHorizontalElement diff --git a/doc/images/JKQTPViolinplotVerticalElement_small.png b/doc/images/JKQTPViolinplotVerticalElement_small.png new file mode 100644 index 0000000000..98088d5578 Binary files /dev/null and b/doc/images/JKQTPViolinplotVerticalElement_small.png differ diff --git a/doc/images/jkqtpstatAddHViolinplotHistogram.png b/doc/images/jkqtpstatAddHViolinplotHistogram.png new file mode 100644 index 0000000000..0436096875 Binary files /dev/null and b/doc/images/jkqtpstatAddHViolinplotHistogram.png differ diff --git a/doc/images/jkqtpstatAddHViolinplotHistogramAndOutliers.png b/doc/images/jkqtpstatAddHViolinplotHistogramAndOutliers.png new file mode 100644 index 0000000000..ae64c2a588 Binary files /dev/null and b/doc/images/jkqtpstatAddHViolinplotHistogramAndOutliers.png differ diff --git a/doc/images/jkqtpstatAddHViolinplotKDE.png b/doc/images/jkqtpstatAddHViolinplotKDE.png new file mode 100644 index 0000000000..da37387b88 Binary files /dev/null and b/doc/images/jkqtpstatAddHViolinplotKDE.png differ diff --git a/doc/images/jkqtpstatAddHViolinplotKDEAndOutliers.png b/doc/images/jkqtpstatAddHViolinplotKDEAndOutliers.png new file mode 100644 index 0000000000..fb7f51392e Binary files /dev/null and b/doc/images/jkqtpstatAddHViolinplotKDEAndOutliers.png differ diff --git a/doc/images/jkqtpstatAddVViolinplotHistogram.png b/doc/images/jkqtpstatAddVViolinplotHistogram.png new file mode 100644 index 0000000000..dcd026c0fa Binary files /dev/null and b/doc/images/jkqtpstatAddVViolinplotHistogram.png differ diff --git a/doc/images/jkqtpstatAddVViolinplotHistogramAndOutliers.png b/doc/images/jkqtpstatAddVViolinplotHistogramAndOutliers.png new file mode 100644 index 0000000000..081d1fc10d Binary files /dev/null and b/doc/images/jkqtpstatAddVViolinplotHistogramAndOutliers.png differ diff --git a/doc/images/jkqtpstatAddVViolinplotKDE.png b/doc/images/jkqtpstatAddVViolinplotKDE.png new file mode 100644 index 0000000000..656df4c5ef Binary files /dev/null and b/doc/images/jkqtpstatAddVViolinplotKDE.png differ diff --git a/doc/images/jkqtpstatAddVViolinplotKDEAndOutliers.png b/doc/images/jkqtpstatAddVViolinplotKDEAndOutliers.png new file mode 100644 index 0000000000..7da10abb23 Binary files /dev/null and b/doc/images/jkqtpstatAddVViolinplotKDEAndOutliers.png differ diff --git a/examples/simpletest_violinplot/README.md b/examples/simpletest_violinplot/README.md index 5741663f82..8ef1a46b44 100644 --- a/examples/simpletest_violinplot/README.md +++ b/examples/simpletest_violinplot/README.md @@ -107,5 +107,17 @@ Finally note that if you use `JKQTPViolinplotHorizontalElement` instead of the ` ![jkqtplotter_simpletest_violinplot_hor](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_violinplot_hor.png) +# Adapters as shortcuts to drawing Violin Plots +Note that there also exist "adapters" that allow to draw violin plots in one line of code: +```.cpp + jkqtpstatAddVViolinplotHistogramAndOutliers(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -5); + jkqtpstatAddHViolinplotHistogramAndOutliers(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -5); + jkqtpstatAddVViolinplotHistogram(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -10); + jkqtpstatAddHViolinplotHistogram(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -10); + jkqtpstatAddVViolinplotKDEAndOutliers(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -15); + jkqtpstatAddHViolinplotKDEAndOutliers(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -15); + jkqtpstatAddVViolinplotKDE(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -20); + jkqtpstatAddHViolinplotKDE(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -20); +``` diff --git a/examples/simpletest_violinplot/jkqtplotter_simpletest_violinplot.cpp b/examples/simpletest_violinplot/jkqtplotter_simpletest_violinplot.cpp index 7810d9882f..c39d6f2050 100644 --- a/examples/simpletest_violinplot/jkqtplotter_simpletest_violinplot.cpp +++ b/examples/simpletest_violinplot/jkqtplotter_simpletest_violinplot.cpp @@ -137,6 +137,17 @@ void showPlot() { gViol3->setViolinPositionMode(pos); gViol3->setTitle("box violin plot "+d3_latex); + // Note that there also exist "adapters" that allow to draw violin plots in one line of code: + /*jkqtpstatAddVViolinplotHistogramAndOutliers(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -5); + jkqtpstatAddHViolinplotHistogramAndOutliers(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -5); + jkqtpstatAddVViolinplotHistogram(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -10); + jkqtpstatAddHViolinplotHistogram(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -10); + jkqtpstatAddVViolinplotKDEAndOutliers(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -15); + jkqtpstatAddHViolinplotKDEAndOutliers(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -15); + jkqtpstatAddVViolinplotKDE(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -20); + jkqtpstatAddHViolinplotKDE(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -20); + */ + // autoscale and style the plot plot->zoomToFit(); plot->getPlotter()->setKeyPosition(JKQTPKeyInsideBottomRight); diff --git a/lib/jkqtcommon/jkqtpstatbasics.h b/lib/jkqtcommon/jkqtpstatbasics.h index 5e5f2ecb09..1de8886f01 100644 --- a/lib/jkqtcommon/jkqtpstatbasics.h +++ b/lib/jkqtcommon/jkqtpstatbasics.h @@ -967,7 +967,7 @@ inline void jkqtpstat5NumberStatisticsAndOutliersOfSortedVector(const TVector& d \see https://en.wikipedia.org/wiki/Five-number_summary, jkqtpstatAddVBoxplotAndOutliers, jkqtpstatAddHBoxplotAndOutliers, jkqtpstatAddVBoxplot, jkqtpstatAddHBoxplot, \ref JKQTPlotterBasicJKQTPDatastoreStatistics */ template -inline void jkqtpstat5NumberStatistics(InputIt first, InputIt last, double* minimum=nullptr, double minimumQuantile=0, double* median=nullptr, double* maximum=nullptr, double maximumQuantile=1, double quantile1Spec=0.25, double* quantile1=nullptr, double quantile2Spec=0.75, double* quantile2=nullptr, double* IQR=nullptr, double* IQRSignificance=nullptr, size_t* Noutput=nullptr) { +inline void jkqtpstat5NumberStatistics(InputIt first, InputIt last, double* minimum, double minimumQuantile=0, double* median=nullptr, double* maximum=nullptr, double maximumQuantile=1, double quantile1Spec=0.25, double* quantile1=nullptr, double quantile2Spec=0.75, double* quantile2=nullptr, double* IQR=nullptr, double* IQRSignificance=nullptr, size_t* Noutput=nullptr) { std::vector dataFiltered; jkqtpstatFilterGoodFloat(first, last, std::back_inserter(dataFiltered)); std::sort(dataFiltered.begin(), dataFiltered.end()); diff --git a/lib/jkqtplotter/jkqtpgraphsstatisticsadaptors.h b/lib/jkqtplotter/jkqtpgraphsstatisticsadaptors.h index 38bb6d74b6..f698dd3873 100644 --- a/lib/jkqtplotter/jkqtpgraphsstatisticsadaptors.h +++ b/lib/jkqtplotter/jkqtpgraphsstatisticsadaptors.h @@ -32,6 +32,7 @@ #include "jkqtplotter/jkqtpgraphscontour.h" #include "jkqtplotter/jkqtpgraphsimpulses.h" #include "jkqtplotter/jkqtpgraphsfilledcurve.h" +#include "jkqtplotter/jkqtpgraphsviolinplot.h" #ifndef JKQTPGRAPHSSTATISTICSADAPTORS_H_INCLUDED @@ -252,6 +253,554 @@ inline std::pair jk + + + + + +/*! \brief add a JKQTPViolinplotHorizontalElement to the given plotter, where the Violinplot values are calculated from the data range \a first ... \a last , uses a kernel density estimate as density distribution estimate + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputIt standard iterator type of \a first and \a last. + \param plotter the plotter to which to add the resulting graph + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param violinposY y-coordinate of the Violinplot + \param kernel the kernel function to use (e.g. jkqtpstatKernel1DGaussian() ) + \param bandwidth bandwidth used for the KDE, if <0 then \c jkqtpstatEstimateKDEBandwidth(first,last) is called + \param distBasename name basing for added columns + \param violinDistSamples number of samples of the distribution (between min and max) + \return a Violinplot element with its values initialized from the given data range + + Example: + \code + jkqtpstatAddHViolinplotKDE(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -20); + \endcode + + \image html JKQTPGraphViolinplot_ViolinHBoth.png + + + \see \ref JKQTPlotterViolinplotGraphs, JKQTPViolinplotHorizontalElement, jkqtpstatKDE1DAutoranged() +*/ +template +inline JKQTPViolinplotHorizontalElement* jkqtpstatAddHViolinplotKDE(JKQTBasePlotter* plotter, InputIt first, InputIt last, double violinposY, const std::function& kernel=std::function(&jkqtpstatKernel1DGaussian), double bandwidth=-1, const QString& distBasename=QString("violin plot distribution"), int violinDistSamples=100) { + if (bandwidth<=0) bandwidth=jkqtpstatEstimateKDEBandwidth(first,last); + JKQTPStat5NumberStatistics stat=jkqtpstat5NumberStatistics(first, last); + size_t cViol1Cat=plotter->getDatastore()->addColumn(distBasename+", category"); + size_t cViol1Freq=plotter->getDatastore()->addColumn(distBasename+", KDE"); + jkqtpstatKDE1DAutoranged(first, last, plotter->getDatastore()->backInserter(cViol1Cat), plotter->getDatastore()->backInserter(cViol1Freq), + violinDistSamples, kernel, bandwidth); + JKQTPViolinplotHorizontalElement* res=new JKQTPViolinplotHorizontalElement(plotter); + res->setMin(stat.minimum); + res->setMax(stat.maximum); + res->setMedian(stat.median); + res->setMean(jkqtpstatAverage(first, last)); + res->setDrawMean(true); + res->setDrawMedian(true); + res->setDrawMinMax(true); + res->setPos(violinposY); + res->setViolinPositionColumn(cViol1Cat); + res->setViolinFrequencyColumn(cViol1Freq); + plotter->addGraph(res); + return res; +} + + + + +/*! \brief add a JKQTPViolinplotHorizontalElement to the given plotter, where the Violinplot values are calculated from the data range \a first ... \a last , uses a histogram as density distribution estimate + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputIt standard iterator type of \a first and \a last. + \param plotter the plotter to which to add the resulting graph + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param violinposY y-coordinate of the Violinplot + \param distBasename name basing for added columns + \param violinDistSamples number of bin of the distribution (between min and max) + \return a Violinplot element with its values initialized from the given data range + + Example: + \code + jkqtpstatAddHViolinplotHistogram(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -10); + \endcode + + \image html jkqtpstatAddHViolinplotHistogram.png + + + \see \ref JKQTPlotterViolinplotGraphs, JKQTPViolinplotHorizontalElement, jkqtpstatHistogram1DAutoranged() +*/ +template +inline JKQTPViolinplotHorizontalElement* jkqtpstatAddHViolinplotHistogram(JKQTBasePlotter* plotter, InputIt first, InputIt last, double violinposY, const QString& distBasename=QString("violin plot distribution"), int violinDistSamples=21) { + JKQTPStat5NumberStatistics stat=jkqtpstat5NumberStatistics(first, last); + size_t cViol1Cat=plotter->getDatastore()->addColumn(distBasename+", category"); + size_t cViol1Freq=plotter->getDatastore()->addColumn(distBasename+", histogram"); + jkqtpstatHistogram1DAutoranged(first, last, plotter->getDatastore()->backInserter(cViol1Cat), plotter->getDatastore()->backInserter(cViol1Freq), + violinDistSamples); + JKQTPViolinplotHorizontalElement* res=new JKQTPViolinplotHorizontalElement(plotter); + res->setMin(stat.minimum); + res->setMax(stat.maximum); + res->setMedian(stat.median); + res->setMean(jkqtpstatAverage(first, last)); + res->setDrawMean(true); + res->setDrawMedian(true); + res->setDrawMinMax(true); + res->setPos(violinposY); + res->setViolinPositionColumn(cViol1Cat); + res->setViolinFrequencyColumn(cViol1Freq); + res->setViolinStyle(JKQTPViolinplotHorizontalElement::StepViolin); + plotter->addGraph(res); + return res; +} + + + + +/*! \brief add a JKQTPViolinplotVerticalElement to the given plotter, where the Violinplot values are calculated from the data range \a first ... \a last , uses a kernel density estimate as density distribution estimate + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputIt standard iterator type of \a first and \a last. + \param plotter the plotter to which to add the resulting graph + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param violinposY y-coordinate of the Violinplot + \param kernel the kernel function to use (e.g. jkqtpstatKernel1DGaussian() ) + \param bandwidth bandwidth used for the KDE, if <0 then \c jkqtpstatEstimateKDEBandwidth(first,last) is called + \param distBasename name basing for added columns + \param violinDistSamples number of samples of the distribution (between min and max) + \return a Violinplot element with its values initialized from the given data range + + Example: + \code + jkqtpstatAddVViolinplotKDE(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -20); + \endcode + + \image html jkqtpstatAddVViolinplotKDE.png + + + \see \ref JKQTPlotterViolinplotGraphs, JKQTPViolinplotVerticalElement, jkqtpstatKDE1DAutoranged() +*/ +template +inline JKQTPViolinplotVerticalElement* jkqtpstatAddVViolinplotKDE(JKQTBasePlotter* plotter, InputIt first, InputIt last, double violinposY, const std::function& kernel=std::function(&jkqtpstatKernel1DGaussian), double bandwidth=-1, const QString& distBasename=QString("violin plot distribution"), int violinDistSamples=100) { + if (bandwidth<=0) bandwidth=jkqtpstatEstimateKDEBandwidth(first,last); + JKQTPStat5NumberStatistics stat=jkqtpstat5NumberStatistics(first, last); + size_t cViol1Cat=plotter->getDatastore()->addColumn(distBasename+", category"); + size_t cViol1Freq=plotter->getDatastore()->addColumn(distBasename+", KDE"); + jkqtpstatKDE1DAutoranged(first, last, plotter->getDatastore()->backInserter(cViol1Cat), plotter->getDatastore()->backInserter(cViol1Freq), + violinDistSamples, kernel, bandwidth); + JKQTPViolinplotVerticalElement* res=new JKQTPViolinplotVerticalElement(plotter); + res->setMin(stat.minimum); + res->setMax(stat.maximum); + res->setMedian(stat.median); + res->setMean(jkqtpstatAverage(first, last)); + res->setDrawMean(true); + res->setDrawMedian(true); + res->setDrawMinMax(true); + res->setPos(violinposY); + res->setViolinPositionColumn(cViol1Cat); + res->setViolinFrequencyColumn(cViol1Freq); + plotter->addGraph(res); + return res; +} + + + + +/*! \brief add a JKQTPViolinplotVerticalElement to the given plotter, where the Violinplot values are calculated from the data range \a first ... \a last , uses a histogram as density distribution estimate + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputIt standard iterator type of \a first and \a last. + \param plotter the plotter to which to add the resulting graph + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param violinposY y-coordinate of the Violinplot + \param distBasename name basing for added columns + \param violinDistSamples number of bin of the distribution (between min and max) + \return a Violinplot element with its values initialized from the given data range + + Example: + \code + jkqtpstatAddVViolinplotHistogram(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -10); + \endcode + + \image html jkqtpstatAddVViolinplotHistogram.png + + + \see \ref JKQTPlotterViolinplotGraphs, JKQTPViolinplotVerticalElement, jkqtpstatHistogram1DAutoranged() +*/ +template +inline JKQTPViolinplotVerticalElement* jkqtpstatAddVViolinplotHistogram(JKQTBasePlotter* plotter, InputIt first, InputIt last, double violinposY, const QString& distBasename=QString("violin plot distribution"), int violinDistSamples=21) { + JKQTPStat5NumberStatistics stat=jkqtpstat5NumberStatistics(first, last); + size_t cViol1Cat=plotter->getDatastore()->addColumn(distBasename+", category"); + size_t cViol1Freq=plotter->getDatastore()->addColumn(distBasename+", histogram"); + jkqtpstatHistogram1DAutoranged(first, last, plotter->getDatastore()->backInserter(cViol1Cat), plotter->getDatastore()->backInserter(cViol1Freq), + violinDistSamples); + JKQTPViolinplotVerticalElement* res=new JKQTPViolinplotVerticalElement(plotter); + res->setMin(stat.minimum); + res->setMax(stat.maximum); + res->setMedian(stat.median); + res->setMean(jkqtpstatAverage(first, last)); + res->setDrawMean(true); + res->setDrawMedian(true); + res->setDrawMinMax(true); + res->setPos(violinposY); + res->setViolinPositionColumn(cViol1Cat); + res->setViolinFrequencyColumn(cViol1Freq); + res->setViolinStyle(JKQTPViolinplotVerticalElement::StepViolin); + plotter->addGraph(res); + return res; +} + + + + + + + + + + +/*! \brief add a JKQTPViolinplotHorizontalElement and an outliers graph to the given plotter, where the Violinplot values are calculated from the data range \a first ... \a last , uses a kernel density estimate as density distribution estimate + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputIt standard iterator type of \a first and \a last. + \param plotter the plotter to which to add the resulting graph + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param violinposY y-coordinate of the Violinplot + \param kernel the kernel function to use (e.g. jkqtpstatKernel1DGaussian() ) + \param bandwidth bandwidth used for the KDE, if <0 then \c jkqtpstatEstimateKDEBandwidth(first,last) is called + \param minimumQuantile specifies a quantile for the return value minimum (default is 0 for the real minimum, but you could e.g. use 0.05 for the 5% quantile!) + \param maximumQuantile specifies a quantile for the return value maximum (default is 1 for the real maximum, but you could e.g. use 0.95 for the 95% quantile!) + \param distBasename name basing for added columns + \param violinDistSamples number of samples of the distribution (between min and max) + \return a Violinplot element with its values initialized from the given data range + + Example: + \code + jkqtpstatAddHViolinplotKDEAndOutliers(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -15); + \endcode + + \image html jkqtpstatAddHViolinplotKDEAndOutliers.png + + + \see \ref JKQTPlotterViolinplotGraphs, JKQTPViolinplotHorizontalElement, jkqtpstatKDE1DAutoranged() +*/ +template +inline std::pair jkqtpstatAddHViolinplotKDEAndOutliers(JKQTBasePlotter* plotter, InputIt first, InputIt last, double violinposY, const std::function& kernel=std::function(&jkqtpstatKernel1DGaussian), double bandwidth=-1, double minimumQuantile=0.03, double maximumQuantile=0.97, const QString& distBasename=QString("violin plot distribution"), int violinDistSamples=100) { + size_t cOutliersY=plotter->getDatastore()->addColumn(distBasename+", outliers, value"); + std::vector datain, datause; + std::copy(first, last, std::back_inserter(datain)); + std::sort(datain.begin(), datain.end()); + datause.reserve(datain.size()); + size_t i0=jkqtp_boundedRoundTo(0,minimumQuantile*static_cast(datain.size()),datain.size()-1); + size_t i1=jkqtp_boundedRoundTo(0,maximumQuantile*static_cast(datain.size()),datain.size()-1); + for (size_t i=0; i=i1) { + plotter->getDatastore()->appendToColumn(cOutliersY, datain[i]); + } else { + datause.push_back(datain[i]); + } + } + + + + if (datause.size()>0) { + if (bandwidth<=0) bandwidth=jkqtpstatEstimateKDEBandwidth(datause.begin(), datause.end()); + size_t cViol1Cat=plotter->getDatastore()->addColumn(distBasename+", category"); + size_t cViol1Freq=plotter->getDatastore()->addColumn(distBasename+", KDE"); + jkqtpstatKDE1DAutoranged(datause.begin(), datause.end(), plotter->getDatastore()->backInserter(cViol1Cat), plotter->getDatastore()->backInserter(cViol1Freq), + violinDistSamples, kernel, bandwidth); + JKQTPViolinplotHorizontalElement* res=new JKQTPViolinplotHorizontalElement(plotter); + res->setMin(datause[0]); + res->setMax(datause[datause.size()-1]); + res->setMedian(jkqtpstatMedianOfSortedVector(datause)); + res->setMean(jkqtpstatAverage(datause.begin(), datause.end())); + res->setDrawMean(true); + res->setDrawMedian(true); + res->setDrawMinMax(true); + res->setPos(violinposY); + res->setViolinPositionColumn(cViol1Cat); + res->setViolinFrequencyColumn(cViol1Freq); + plotter->addGraph(res); + + JKQTPSingleColumnSymbolsGraph* resO=new JKQTPSingleColumnSymbolsGraph(plotter); + resO->setDataColumn(cOutliersY); + resO->setPosition(violinposY); + resO->setPositionScatterStyle(JKQTPSingleColumnSymbolsGraph::NoScatter); + resO->setDataDirection(JKQTPSingleColumnSymbolsGraph::DataDirection::X); + resO->setColor(res->getKeyLabelColor()); + resO->setTitle(""); + + plotter->addGraph(res); + plotter->addGraph(resO); + return std::pair(res,resO); + } else { + return std::pair(nullptr,nullptr); + } + +} + + + + + +/*! \brief add a JKQTPViolinplotHorizontalElement and an outliers graph to the given plotter, where the Violinplot values are calculated from the data range \a first ... \a last , uses a histogram as density distribution estimate + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputIt standard iterator type of \a first and \a last. + \param plotter the plotter to which to add the resulting graph + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param violinposY y-coordinate of the Violinplot + \param minimumQuantile specifies a quantile for the return value minimum (default is 0 for the real minimum, but you could e.g. use 0.05 for the 5% quantile!) + \param maximumQuantile specifies a quantile for the return value maximum (default is 1 for the real maximum, but you could e.g. use 0.95 for the 95% quantile!) + \param distBasename name basing for added columns + \param violinDistSamples number of samples of the distribution (between min and max) + \return a Violinplot element with its values initialized from the given data range + + Example: + \code + jkqtpstatAddHViolinplotHistogramAndOutliers(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -5); + \endcode + + \image html jkqtpstatAddHViolinplotHistogramAndOutliers.png + + + \see \ref JKQTPlotterViolinplotGraphs, JKQTPViolinplotHorizontalElement, jkqtpstatHistogram1DAutoranged() +*/ +template +inline std::pair jkqtpstatAddHViolinplotHistogramAndOutliers(JKQTBasePlotter* plotter, InputIt first, InputIt last, double violinposY, double minimumQuantile=0.03, double maximumQuantile=0.97, const QString& distBasename=QString("violin plot distribution"), int violinDistSamples=21) { + size_t cOutliersY=plotter->getDatastore()->addColumn(distBasename+", outliers, value"); + std::vector datain, datause; + std::copy(first, last, std::back_inserter(datain)); + std::sort(datain.begin(), datain.end()); + datause.reserve(datain.size()); + size_t i0=jkqtp_boundedRoundTo(0,minimumQuantile*static_cast(datain.size()),datain.size()-1); + size_t i1=jkqtp_boundedRoundTo(0,maximumQuantile*static_cast(datain.size()),datain.size()-1); + for (size_t i=0; i=i1) { + plotter->getDatastore()->appendToColumn(cOutliersY, datain[i]); + } else { + datause.push_back(datain[i]); + } + } + + + + if (datause.size()>0) { + size_t cViol1Cat=plotter->getDatastore()->addColumn(distBasename+", category"); + size_t cViol1Freq=plotter->getDatastore()->addColumn(distBasename+", Histogram"); + jkqtpstatHistogram1DAutoranged(datause.begin(), datause.end(), plotter->getDatastore()->backInserter(cViol1Cat), plotter->getDatastore()->backInserter(cViol1Freq), violinDistSamples); + JKQTPViolinplotHorizontalElement* res=new JKQTPViolinplotHorizontalElement(plotter); + res->setMin(datause[0]); + res->setMax(datause[datause.size()-1]); + res->setMedian(jkqtpstatMedianOfSortedVector(datause)); + res->setMean(jkqtpstatAverage(datause.begin(), datause.end())); + res->setDrawMean(true); + res->setDrawMedian(true); + res->setDrawMinMax(true); + res->setPos(violinposY); + res->setViolinPositionColumn(cViol1Cat); + res->setViolinFrequencyColumn(cViol1Freq); + res->setViolinStyle(JKQTPViolinplotVerticalElement::StepViolin); + plotter->addGraph(res); + + JKQTPSingleColumnSymbolsGraph* resO=new JKQTPSingleColumnSymbolsGraph(plotter); + resO->setDataColumn(cOutliersY); + resO->setPosition(violinposY); + resO->setPositionScatterStyle(JKQTPSingleColumnSymbolsGraph::NoScatter); + resO->setDataDirection(JKQTPSingleColumnSymbolsGraph::DataDirection::X); + resO->setColor(res->getKeyLabelColor()); + resO->setTitle(""); + + plotter->addGraph(res); + plotter->addGraph(resO); + return std::pair(res,resO); + } else { + return std::pair(nullptr,nullptr); + } + +} + + + + + + + + + +/*! \brief add a JKQTPViolinplotVerticalElement and an outliers graph to the given plotter, where the Violinplot values are calculated from the data range \a first ... \a last , uses a kernel density estimate as density distribution estimate + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputIt standard iterator type of \a first and \a last. + \param plotter the plotter to which to add the resulting graph + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param violinposY y-coordinate of the Violinplot + \param kernel the kernel function to use (e.g. jkqtpstatKernel1DGaussian() ) + \param bandwidth bandwidth used for the KDE, if <0 then \c jkqtpstatEstimateKDEBandwidth(first,last) is called + \param minimumQuantile specifies a quantile for the return value minimum (default is 0 for the real minimum, but you could e.g. use 0.05 for the 5% quantile!) + \param maximumQuantile specifies a quantile for the return value maximum (default is 1 for the real maximum, but you could e.g. use 0.95 for the 95% quantile!) + \param distBasename name basing for added columns + \param violinDistSamples number of samples of the distribution (between min and max) + \return a Violinplot element with its values initialized from the given data range + + Example: + \code + jkqtpstatAddVViolinplotKDEAndOutliers(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -15); + \endcode + + \image html jkqtpstatAddVViolinplotKDEAndOutliers.png + + + \see \ref JKQTPlotterViolinplotGraphs, JKQTPViolinplotVerticalElement, jkqtpstatKDE1DAutoranged() +*/ +template +inline std::pair jkqtpstatAddVViolinplotKDEAndOutliers(JKQTBasePlotter* plotter, InputIt first, InputIt last, double violinposY, const std::function& kernel=std::function(&jkqtpstatKernel1DGaussian), double bandwidth=-1, double minimumQuantile=0.03, double maximumQuantile=0.97, const QString& distBasename=QString("violin plot distribution"), int violinDistSamples=100) { + size_t cOutliersY=plotter->getDatastore()->addColumn(distBasename+", outliers, value"); + std::vector datain, datause; + std::copy(first, last, std::back_inserter(datain)); + std::sort(datain.begin(), datain.end()); + datause.reserve(datain.size()); + size_t i0=jkqtp_boundedRoundTo(0,minimumQuantile*static_cast(datain.size()),datain.size()-1); + size_t i1=jkqtp_boundedRoundTo(0,maximumQuantile*static_cast(datain.size()),datain.size()-1); + for (size_t i=0; i=i1) { + plotter->getDatastore()->appendToColumn(cOutliersY, datain[i]); + } else { + datause.push_back(datain[i]); + } + } + + + + if (datause.size()>0) { + if (bandwidth<=0) bandwidth=jkqtpstatEstimateKDEBandwidth(datause.begin(), datause.end()); + size_t cViol1Cat=plotter->getDatastore()->addColumn(distBasename+", category"); + size_t cViol1Freq=plotter->getDatastore()->addColumn(distBasename+", KDE"); + jkqtpstatKDE1DAutoranged(datause.begin(), datause.end(), plotter->getDatastore()->backInserter(cViol1Cat), plotter->getDatastore()->backInserter(cViol1Freq), + violinDistSamples, kernel, bandwidth); + JKQTPViolinplotVerticalElement* res=new JKQTPViolinplotVerticalElement(plotter); + res->setMin(datause[0]); + res->setMax(datause[datause.size()-1]); + res->setMedian(jkqtpstatMedianOfSortedVector(datause)); + res->setMean(jkqtpstatAverage(datause.begin(), datause.end())); + res->setDrawMean(true); + res->setDrawMedian(true); + res->setDrawMinMax(true); + res->setPos(violinposY); + res->setViolinPositionColumn(cViol1Cat); + res->setViolinFrequencyColumn(cViol1Freq); + plotter->addGraph(res); + + JKQTPSingleColumnSymbolsGraph* resO=new JKQTPSingleColumnSymbolsGraph(plotter); + resO->setDataColumn(cOutliersY); + resO->setPosition(violinposY); + resO->setPositionScatterStyle(JKQTPSingleColumnSymbolsGraph::NoScatter); + resO->setDataDirection(JKQTPSingleColumnSymbolsGraph::DataDirection::Y); + resO->setColor(res->getKeyLabelColor()); + resO->setTitle(""); + + plotter->addGraph(res); + plotter->addGraph(resO); + return std::pair(res,resO); + } else { + return std::pair(nullptr,nullptr); + } + +} + + + + + +/*! \brief add a JKQTPViolinplotVerticalElement and an outliers graph to the given plotter, where the Violinplot values are calculated from the data range \a first ... \a last , uses a histogram as density distribution estimate + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputIt standard iterator type of \a first and \a last. + \param plotter the plotter to which to add the resulting graph + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param violinposY y-coordinate of the Violinplot + \param minimumQuantile specifies a quantile for the return value minimum (default is 0 for the real minimum, but you could e.g. use 0.05 for the 5% quantile!) + \param maximumQuantile specifies a quantile for the return value maximum (default is 1 for the real maximum, but you could e.g. use 0.95 for the 95% quantile!) + \param distBasename name basing for added columns + \param violinDistSamples number of samples of the distribution (between min and max) + \return a Violinplot element with its values initialized from the given data range + + Example: + \code + jkqtpstatAddVViolinplotHistogramAndOutliers(plot->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -5); + \endcode + + \image html jkqtpstatAddVViolinplotHistogramAndOutliers.png + + + \see \ref JKQTPlotterViolinplotGraphs, JKQTPViolinplotVerticalElement, jkqtpstatHistogram1DAutoranged() +*/ +template +inline std::pair jkqtpstatAddVViolinplotHistogramAndOutliers(JKQTBasePlotter* plotter, InputIt first, InputIt last, double violinposY, double minimumQuantile=0.03, double maximumQuantile=0.97, const QString& distBasename=QString("violin plot distribution"), int violinDistSamples=21) { + size_t cOutliersY=plotter->getDatastore()->addColumn(distBasename+", outliers, value"); + std::vector datain, datause; + std::copy(first, last, std::back_inserter(datain)); + std::sort(datain.begin(), datain.end()); + datause.reserve(datain.size()); + size_t i0=jkqtp_boundedRoundTo(0,minimumQuantile*static_cast(datain.size()),datain.size()-1); + size_t i1=jkqtp_boundedRoundTo(0,maximumQuantile*static_cast(datain.size()),datain.size()-1); + for (size_t i=0; i=i1) { + plotter->getDatastore()->appendToColumn(cOutliersY, datain[i]); + } else { + datause.push_back(datain[i]); + } + } + + + + if (datause.size()>0) { + size_t cViol1Cat=plotter->getDatastore()->addColumn(distBasename+", category"); + size_t cViol1Freq=plotter->getDatastore()->addColumn(distBasename+", Histogram"); + jkqtpstatHistogram1DAutoranged(datause.begin(), datause.end(), plotter->getDatastore()->backInserter(cViol1Cat), plotter->getDatastore()->backInserter(cViol1Freq), violinDistSamples); + JKQTPViolinplotVerticalElement* res=new JKQTPViolinplotVerticalElement(plotter); + res->setMin(datause[0]); + res->setMax(datause[datause.size()-1]); + res->setMedian(jkqtpstatMedianOfSortedVector(datause)); + res->setMean(jkqtpstatAverage(datause.begin(), datause.end())); + res->setDrawMean(true); + res->setDrawMedian(true); + res->setDrawMinMax(true); + res->setPos(violinposY); + res->setViolinPositionColumn(cViol1Cat); + res->setViolinFrequencyColumn(cViol1Freq); + res->setViolinStyle(JKQTPViolinplotVerticalElement::StepViolin); + plotter->addGraph(res); + + JKQTPSingleColumnSymbolsGraph* resO=new JKQTPSingleColumnSymbolsGraph(plotter); + resO->setDataColumn(cOutliersY); + resO->setPosition(violinposY); + resO->setPositionScatterStyle(JKQTPSingleColumnSymbolsGraph::NoScatter); + resO->setDataDirection(JKQTPSingleColumnSymbolsGraph::DataDirection::Y); + resO->setColor(res->getKeyLabelColor()); + resO->setTitle(""); + + plotter->addGraph(res); + plotter->addGraph(resO); + return std::pair(res,resO); + } else { + return std::pair(nullptr,nullptr); + } + +} + + + + + + + + /*! \brief calculate an autoranged histogram and add a JKQTPBarVerticalGraph to the given plotter, where the histogram is calculated from the data range \a first ... \a last, bins defined by their number \ingroup jkqtptools_math_statistics_adaptors