diff --git a/JKQtPlotterBuildAllExamples.pro b/JKQtPlotterBuildAllExamples.pro index f115ba8944..c9dffb0628 100644 --- a/JKQtPlotterBuildAllExamples.pro +++ b/JKQtPlotterBuildAllExamples.pro @@ -84,6 +84,7 @@ addSimpleTest(datastore_iterators) addSimpleTest(datastore_statistics) addSimpleTest(datastore_statistics_2d) addSimpleTest(datastore_regression) +addSimpleTest(datastore_groupedstat) addSimpleTest(contourplot) #addSimpleTest(rgbimageplot_opencv) #addSimpleTest(imageplot_opencv) diff --git a/doc/dox/examples_and_tutorials.dox b/doc/dox/examples_and_tutorials.dox index bcbe5aa0dd..0d2a421b2b 100644 --- a/doc/dox/examples_and_tutorials.dox +++ b/doc/dox/examples_and_tutorials.dox @@ -162,6 +162,9 @@ All test-projects are Qt-projects that use qmake to build. You can load them int \image html jkqtplotter_simpletest_datastore_regression_small.png \subpage JKQTPlotterBasicJKQTPDatastoreRegression Advanced 1-Dimensional Statistical Computation with JKQTPDatastore
using the internal statistics library
Regression Analysis (with the Statistics Library)
robust regression (IRLS)
weighted regression
non-linear regression
polynomial fitting + \image html jkqtplotter_simpletest_datastore_groupedstat_small.png + \subpage JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat + Advanced 1-Dimensional Statistical Computation with JKQTPDatastore
grouped statistics
error indicators from data
boxplots \image html jkqtplotter_simpletest_datastore_statistics_2d_small.png \subpage JKQTPlotterBasicJKQTPDatastoreStatistics2D Advanced 2-Dimensional Statistical Computation with JKQTPDatastore
using the internal statistics library (see \ref jkqtptools_math_statistics )
histograms
kernel density estimates (KDE) diff --git a/doc/dox/jkqtplotter.dox b/doc/dox/jkqtplotter.dox index 1d357326a2..92ed87ccc2 100644 --- a/doc/dox/jkqtplotter.dox +++ b/doc/dox/jkqtplotter.dox @@ -37,7 +37,9 @@ This group assembles a basic set of linear algebra methods, including matrix inv This group contains a statistics library, which offers several basic methods and is based on an iterator interface: - \ref jkqtptools_math_statistics_basic + - \ref jkqtptools_math_statistics_grouped - \ref jkqtptools_math_statistics_regression + - \ref jkqtptools_math_statistics_poly - \ref jkqtptools_math_statistics_1dhist - \ref jkqtptools_math_statistics_2dhist - \ref jkqtptools_math_statistics_1dkde @@ -67,9 +69,15 @@ All statistics functions use all values in the given range and convert each valu \defgroup jkqtptools_math_statistics_basic Basic statistics \ingroup jkqtptools_math_statistics +\defgroup jkqtptools_math_statistics_grouped Grouped statistics +\ingroup jkqtptools_math_statistics + \defgroup jkqtptools_math_statistics_regression Regression Analysis \ingroup jkqtptools_math_statistics +\defgroup jkqtptools_math_statistics_poly Polynomial Fits/Regression +\ingroup jkqtptools_math_statistics + \defgroup jkqtptools_math_statistics_1dhist 1-dimensional Histograms \ingroup jkqtptools_math_statistics diff --git a/examples/README.md b/examples/README.md index 71397b14da..79b9240699 100644 --- a/examples/README.md +++ b/examples/README.md @@ -66,6 +66,7 @@ All test-projects are Qt-projects that use qmake to build. You can load them int | [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_iterators_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore_iterators) | [Tutorial: Iterator-based access to JKQTPDatastore](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore_iterators) | Iterator-based Data Management with JKQTPDatastore | | [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_datastore_statistics_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore_statistics) | [Tutorial: Advanced 1-Dimensional Statistics with JKQTPDatastore](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore_statistics) | Advanced 1-Dimensional Statistical Computation with JKQTPDatastore
using the internal statistics library
basic statistics (mean, standard deviation, ...)
boxplots
histograms
kernel density estimates (KDE) | | [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_datastore_regression_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore_regression) | [Tutorial: Regression Analysis (with the Statistics Library)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore_regression) | Advanced 1-Dimensional Statistical Computation with JKQTPDatastore
using the internal statistics library
Regression Analysis (with the Statistics Library)
robust regression (IRLS)
weighted regression
non-linear regression
polynomial fitting | +| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_datastore_groupedstat_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore_groupedstat) | [Tutorial: 1-Dimensional Group Statistics (with the Statistics Library)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore_groupedstat) | Advanced 1-Dimensional Statistical Computation with JKQTPDatastore
grouped statistics
error indicators from data
boxplots | | [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_datastore_statistics_2d_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore_statistics_2d) | [Tutorial: Advanced 2-Dimensional Statistics with JKQTPDatastore](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore_statistics_2d) | Advanced 2-Dimensional Statistical Computation with JKQTPDatastore
using the internal statistics library
histograms
kernel density estimates (KDE) | diff --git a/examples/simpletest_boxplot/README.md b/examples/simpletest_boxplot/README.md index 1f49cd5ed6..641e4b4b64 100644 --- a/examples/simpletest_boxplot/README.md +++ b/examples/simpletest_boxplot/README.md @@ -1,6 +1,13 @@ # Example (JKQTPlotter): Boxplots {#JKQTPlotterBoxplotsGraphs} + This project (see [`simpletest_boxplot`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_boxplot) demonstrates how to use JKQTPlotter to draw box plots using the classes `JKQTPBoxplotVerticalGraph` and `JKQTPBoxplotHorizontalGraph`. +[JKQTPlotterBasicJKQTPDatastoreStatistics]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics "Advanced 1-Dimensional Statistics with JKQTPDatastore" +[statisticslibrary]: @ref jkqtptools_math_statistics "JKQTPlotter Statistics Library" +[JKQTPlotterBoxplotStyling]: @ref JKQTPlotterBoxplotStyling "Styling different aspects of boxplots" + +***Note*** that this example explains how to add boxplots to a graph by hand, i.e. by calculating all the statistical properties for the boxplots by hand. The internal [statisticslibrary] offers methods to perform these calculations, which are explained in the tutorial [JKQTPlotterBasicJKQTPDatastoreStatistics] in detail. Additional advanced styling of boxplots is covered by the example [JKQTPlotterBoxplotStyling]. + The source code of the main application is (see [`jkqtplotter_simpletest_boxplot.cpp`](jkqtplotter_simpletest_boxplot.cpp). After adding all necessary data to the JKQTDatastore: diff --git a/examples/simpletest_datastore/README.md b/examples/simpletest_datastore/README.md index b23236a8a1..f862984fab 100644 --- a/examples/simpletest_datastore/README.md +++ b/examples/simpletest_datastore/README.md @@ -1,10 +1,10 @@ # Tutorial (JKQTPDatastore): Basic Usage of JKQTPDatastore {#JKQTPlotterBasicJKQTPDatastore} - [JKQTPlotterBasicJKQTPDatastore]: @ref JKQTPlotterBasicJKQTPDatastore "Basic Usage of JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreIterators]: @ref JKQTPlotterBasicJKQTPDatastoreIterators "Iterator-Based usage of JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreStatistics]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics "Advanced 1-Dimensional Statistics with JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreRegression]: @ref JKQTPlotterBasicJKQTPDatastoreRegression "Regression Analysis (with the Statistics Library)" +[JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat]: @ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat "1-Dimensional Group Statistics with JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreStatistics2D]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics2D "Advanced 2-Dimensional Statistics with JKQTPDatastore" [statisticslibrary]: @ref jkqtptools_math_statistics "JKQTPlotter Statistics Library" @@ -14,8 +14,10 @@ This tutorial project (see `./examples/simpletest_datastore/`) explains several - [JKQTPlotterBasicJKQTPDatastore] - [JKQTPlotterBasicJKQTPDatastoreIterators] - [JKQTPlotterBasicJKQTPDatastoreStatistics] - - [JKQTPlotterBasicJKQTPDatastoreStatistics2D] - [JKQTPlotterBasicJKQTPDatastoreRegression] + - [JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat] + - [JKQTPlotterBasicJKQTPDatastoreStatistics2D] + [TOC] diff --git a/examples/simpletest_datastore_groupedstat/README.md b/examples/simpletest_datastore_groupedstat/README.md new file mode 100644 index 0000000000..5c7c95c6ee --- /dev/null +++ b/examples/simpletest_datastore_groupedstat/README.md @@ -0,0 +1,255 @@ +# Tutorial (JKQTPDatastore): 1-Dimensional Group Statistics with JKQTPDatastore {#JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat} + +[JKQTPlotterBasicJKQTPDatastore]: @ref JKQTPlotterBasicJKQTPDatastore "Basic Usage of JKQTPDatastore" +[JKQTPlotterBasicJKQTPDatastoreIterators]: @ref JKQTPlotterBasicJKQTPDatastoreIterators "Iterator-Based usage of JKQTPDatastore" +[JKQTPlotterBasicJKQTPDatastoreStatistics]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics "Advanced 1-Dimensional Statistics with JKQTPDatastore" +[JKQTPlotterBasicJKQTPDatastoreRegression]: @ref JKQTPlotterBasicJKQTPDatastoreRegression "Regression Analysis (with the Statistics Library)" +[JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat]: @ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat "1-Dimensional Group Statistics with JKQTPDatastore" +[JKQTPlotterBasicJKQTPDatastoreStatistics2D]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics2D "Advanced 2-Dimensional Statistics with JKQTPDatastore" +[statisticslibrary]: @ref jkqtptools_math_statistics "JKQTPlotter Statistics Library" + +This tutorial project (see `./examples/simpletest_datastore_groupedstat/`) explains several advanced functions of JKQTPDatastore in combination with the [[statisticslibrary]] conatined in JKQTPlotter. + +***Note*** that there are additional tutorial explaining other aspects of data mangement in JKQTPDatastore: + - [JKQTPlotterBasicJKQTPDatastore] + - [JKQTPlotterBasicJKQTPDatastoreIterators] + - [JKQTPlotterBasicJKQTPDatastoreStatistics] + - [JKQTPlotterBasicJKQTPDatastoreRegression] + - [JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat] + - [JKQTPlotterBasicJKQTPDatastoreStatistics2D] + +[TOC] + +The source code of the main application can be found in [`jkqtplotter_simpletest_datastore_groupedstat.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore_groupedstat/jkqtplotter_simpletest_datastore_groupedstat.cpp). +This tutorial cites only parts of this code to demonstrate different ways of working with data for the graphs. + +# Barcharts & Boxplots from categorized data + +## Generating a Dataset for Grouped Barcharts + +To demonstrate the grouped statistics, we first have to generate a dataset. The datapoints consist of pairs ``, where the groups are encoded by the numbers 1,2,3 and in each group, several measurements are taken: +```.cpp + size_t colBarRawGroup=datastore1->addColumn("barchart, rawdata, group"); + size_t colBarRawValue=datastore1->addColumn("barchart, rawdata, value"); + + // data for group 1 + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 1, 1.1); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 1, 1.5); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 1, 0.8); + // ... + + // data for group 2 + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 2, 2.2); + // ... + + // data for group 3 + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 3, 4.1); + // ... + +``` + +Note that the data does not have to be sorted. You can add the dataset in any order! + +This dataset can be visualized with a simple scatter plot: +```.cpp + JKQTPXYLineGraph* gScatterForBar; + plotbarchart->addGraph(gScatterForBar=new JKQTPXYLineGraph(plotbarchart)); + gScatterForBar->setXYColumns(colBarRawGroup, colBarRawValue); + gScatterForBar->setDrawLine(false); + gScatterForBar->setSymbolType(JKQTPCross); + gScatterForBar->setSymbolSize(5); + gScatterForBar->setSymbolColor(QColorWithAlphaF(QColor("red"), 0.5)); +``` + +![jkqtplotter_simpletest_datastore_groupedstat_barchartrawdata](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_datastore_groupedstat_barchartrawdata.png) + +## Calculating Grouped Statistics for a Barchart + +Now we want to draw a barchart for every group, which indicates the average in each group. This is done using methods from the statistics library. +First we need to group the data using `jkqtpstatGroupData()`, which assembles the data points in each group groupeddataBar +```.cpp + std::map > groupeddataBar; + jkqtpstatGroupData(datastore1->begin(colBarRawGroup), datastore1->end(colBarRawGroup), + datastore1->begin(colBarRawValue), datastore1->end(colBarRawValue), + groupeddataBar); +``` +Now we can calculate the statistics for each group separately: Data is collected in new columns `colBarGroup`, `colBarAverage` and `colBarStdDev`. The statistics is then calculated by simply iterating over `groupeddataBar` and calling functions like `jkqtpstatAverage()` for each group: +```.cpp + size_t colBarGroup=datastore1->addColumn("barchart, group"); + size_t colBarAverage=datastore1->addColumn("barchart, group-average"); + size_t colBarStdDev=datastore1->addColumn("barchart, group-stddev"); + + for (auto it=groupeddataBar.begin(); it!=groupeddataBar.end(); ++it) { + datastore1->appendToColumn(colBarGroup, it->first); + datastore1->appendToColumn(colBarAverage, jkqtpstatAverage(it->second.begin(), it->second.end())); + datastore1->appendToColumn(colBarStdDev, jkqtpstatStdDev(it->second.begin(), it->second.end())); + } +``` + +Finally the calculated groups are drawn: +```.cpp + JKQTPBarVerticalErrorGraph* gBar; + plotbarchart->addGraph(gBar=new JKQTPBarVerticalErrorGraph(plotbarchart)); + gBar->setXYColumns(colBarGroup, colBarAverage); + gBar->setYErrorColumn(static_cast(colBarStdDev)); +``` + +![jkqtplotter_simpletest_datastore_groupedstat_barchart](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_datastore_groupedstat_barchart.png) + +In order to safe yo the typing of the code above, shortcuts in the form of adaptors exist: +```.cpp + jkqtpstatAddYErrorBarGraph(plotbarchart->getPlotter(), + datastore1->begin(colBarRawGroup), datastore1->end(colBarRawGroup), + datastore1->begin(colBarRawValue), datastore1->end(colBarRawValue)); +``` +Also other flavors exist that generate different graphs (see the JKQTPlotter documentation): + - `jkqtpstatAddYErrorLineGraph()` / `jkqtpstatAddXErrorLineGraph()` + - `jkqtpstatAddYErrorBarGraph()` / `jkqtpstatAddXErrorBarGraph()` + - `jkqtpstatAddYErrorImpulsesGraph()` / `jkqtpstatAddXErrorImpulsesGraph()` + - `jkqtpstatAddYErrorParametrizedScatterGraph()` / `jkqtpstatAddXErrorParametrizedScatterGraph()` + - `jkqtpstatAddYErrorFilledCurveGraph()` / `jkqtpstatAddXErrorFilledCurveGraph()` + - `jkqtpstatAddYErrorGraph()` / `jkqtpstatAddXErrorGraph()` + + +## Calculating Grouped Statistics for a Boxplot + +With the methods above we can also calculate more advanced statistics, like e.g. boxplots: +```.cpp + size_t colBarMedian=datastore1->addColumn("barchart, group-median"); + size_t colBarMin=datastore1->addColumn("barchart, group-min"); + size_t colBarMax=datastore1->addColumn("barchart, group-max"); + size_t colBarQ25=datastore1->addColumn("barchart, group-Q25"); + size_t colBarQ75=datastore1->addColumn("barchart, group-Q75"); + for (auto it=groupeddataBar.begin(); it!=groupeddataBar.end(); ++it) { + datastore1->appendToColumn(colBarMedian, jkqtpstatMedian(it->second.begin(), it->second.end())); + datastore1->appendToColumn(colBarMin, jkqtpstatMinimum(it->second.begin(), it->second.end())); + datastore1->appendToColumn(colBarMax, jkqtpstatMaximum(it->second.begin(), it->second.end())); + datastore1->appendToColumn(colBarQ25, jkqtpstatQuantile(it->second.begin(), it->second.end(), 0.25)); + datastore1->appendToColumn(colBarQ75, jkqtpstatQuantile(it->second.begin(), it->second.end(), 0.75)); + } +``` +The result can be plotted using JKQTPBoxplotVerticalGraph, which receives a column for each value class of the final plot: +```.cpp + JKQTPBoxplotVerticalGraph* gBoxplot; + plotboxplot->addGraph(gBoxplot=new JKQTPBoxplotVerticalGraph(plotboxplot)); + gBoxplot->setPositionColumn(colBarGroup); + gBoxplot->setMinColumn(colBarMin); + gBoxplot->setMaxColumn(colBarMax); + gBoxplot->setMedianColumn(colBarMedian); + gBoxplot->setPercentile25Column(colBarQ25); + gBoxplot->setPercentile75Column(colBarQ75); +``` + +![jkqtplotter_simpletest_datastore_groupedstat_boxplot](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_datastore_groupedstat_boxplot.png) + +In order to safe yo the typing of the code above, shortcuts in the form of adaptors exist: +```.cpp + jkqtpstatAddHBoxplotsAndOutliers(plotboxplot->getPlotter(), + datastore1->begin(colBarRawGroup), datastore1->end(colBarRawGroup), + datastore1->begin(colBarRawValue), datastore1->end(colBarRawValue)); +``` +Also other flavors exist that generate different graphs (see the JKQTPlotter documentation): + - `jkqtpstatAddVBoxplotsAndOutliers()` / `jkqtpstatAddHBoxplotsAndOutliers()` + - `jkqtpstatVAddBoxplots()` / `jkqtpstatHAddBoxplots()` + - `jkqtpstatAddBoxplots()` + + +# (Scatter-)Graphs with X/Y-errors from Categorized Data + +## Dataset for XY Scatter Graphs + +First we generate a second dataset, which is going to be used for a scaterplot. The datapoints consist of pairs ``, that are based on a parabula with random deviations, both in x- and y-direction: +```.cpp + size_t colScatterRawX=datastore1->addColumn("scatterplot, rawdata, x"); + size_t colScatterRawY=datastore1->addColumn("scatterplot, rawdata, y"); + std::random_device rd; // random number generators: + std::mt19937 gen{rd()}; + std::normal_distribution<> d1{0,0.5}; + const size_t N=100; + const double xmax=3.5; + for (size_t i=0; i(i)-static_cast(N)/2.0)*xmax/(static_cast(N)/2.0); + const double y=jkqtp_sqr(x)+2.0; + datastore1->appendToColumns(colScatterRawX, colScatterRawY, x+d1(gen), y+d1(gen)); + } +``` + +This dataset can be visualized: +```.cpp + JKQTPXYParametrizedScatterGraph* gScatterRaw; + plotscattererrors->addGraph(gScatterRaw=new JKQTPXYParametrizedScatterGraph(plotscattererrors)); + gScatterRaw->setXYColumns(colScatterRawX, colScatterRawY); + gScatterRaw->setDrawLine(false); + gScatterRaw->setSymbolType(JKQTPCross); + gScatterRaw->setSymbolSize(5); +``` + +![jkqtplotter_simpletest_datastore_groupedstat_scatterrawdata](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_datastore_groupedstat_scatterrawdata.png) + +## Calculating x- and y-Errors from Categorized Data + +Now we want to draw a scatterchart of the data, where data-points should be grouped together, in x-intervals of width 0.5. From all the points in each interval, we calculate the in both x- and y-direction the average and standard deviation. First we need to group the data using `jkqtpstatGroupData()`, which assembles the data points in each group groupeddataScatter. For the custom grouping of the datapoints we use the optional functor provided to `jkqtpstatGroupData()`: We use `jkqtpstatGroupingCustomRound1D()` with given parameters 0.25 for the (center) location of the first bin and bin width 0.5. The functor is not built by hand (which would be possible using std::bind), but with the generator function `jkqtpstatMakeGroupingCustomRound1D()`. In addition we use a variant of `jkqtpstatGroupData()`, which outputs a column with the category assigned to every data pair in the input data range: +```.cpp + std::map,std::vector > > groupeddataScatter; + size_t colScatterRawGroup=datastore1->addColumn("scatterplot, rawdata, assigned-group"); + jkqtpstatGroupData(datastore1->begin(colScatterRawX), datastore1->end(colScatterRawX), + datastore1->begin(colScatterRawY), datastore1->end(colScatterRawY), + datastore1->backInserter(colScatterRawGroup), + groupeddataScatter, + jkqtpstatMakeGroupingCustomRound1D(0.25, 0.5)); +``` + +The column colScatterRawGroup can now be used to color the scatter graph: +```.cpp + gScatterRaw->setColorColumn(colScatterRawGroup); +``` + +Now we can calculate the statistics for each group separately: Data is collected in two new columns. Then the statistics is calculated by simply iterating over `groupeddataScatter` and calling functions like `jkqtpstatAverage()` for each group: +```.cpp + size_t colScatterXAvg=datastore1->addColumn("scatter, x, average"); + size_t colScatterXStd=datastore1->addColumn("scatter, x, stddev"); + size_t colScatterYAvg=datastore1->addColumn("scatter, y, average"); + size_t colScatterYStd=datastore1->addColumn("scatter, y, stddev"); + + for (auto it=groupeddataScatter.begin(); it!=groupeddataScatter.end(); ++it) { + datastore1->appendToColumn(colScatterXAvg, jkqtpstatAverage(it->second.first.begin(), it->second.first.end())); + datastore1->appendToColumn(colScatterXStd, jkqtpstatStdDev(it->second.first.begin(), it->second.first.end())); + datastore1->appendToColumn(colScatterYAvg, jkqtpstatAverage(it->second.second.begin(), it->second.second.end())); + datastore1->appendToColumn(colScatterYStd, jkqtpstatStdDev(it->second.second.begin(), it->second.second.end())); + } +``` + +Finally the calculated groups are drawn +```.cpp + JKQTPXYLineErrorGraph* gScatterErr; + plotscattererrors->addGraph(gScatterErr=new JKQTPXYLineErrorGraph(plotscattererrors)); + gScatterErr->setXYColumns(colScatterXAvg, colScatterYAvg); + gScatterErr->setXErrorColumn(static_cast(colScatterXStd)); + gScatterErr->setYErrorColumn(static_cast(colScatterYStd)); + gScatterErr->setSymbolType(JKQTPFilledTriangle); + gScatterErr->setDrawLine(false); +``` + +![jkqtplotter_simpletest_datastore_groupedstat_scatter](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_datastore_groupedstat_scatter.png) + + +In order to safe yo the typing of the code above, shortcuts in the form of adaptors exist: +```.cpp + jkqtpstatAddXYErrorLineGraph(plotscattererrors->getPlotter(), + datastore1->begin(colScatterRawX), datastore1->end(colScatterRawX), + datastore1->begin(colScatterRawY), datastore1->end(colScatterRawY), + jkqtpstatMakeGroupingCustomRound1D(0.25, 0.5)); +``` +Also other flavors exist that generate different graphs (see the JKQTPlotter documentation): + - `jkqtpstatAddXYErrorLineGraph()` + - `jkqtpstatAddXYErrorParametrizedScatterGraph()` + - `jkqtpstatAddXYErrorGraph()` + + +# Screenshot of the full Program + +The output of the full test program [`jkqtplotter_simpletest_datastore_groupedstat.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore_groupedstat/jkqtplotter_simpletest_datastore_groupedstat.cpp) looks like this: + +![jkqtplotter_simpletest_datastore_groupedstat](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_datastore_groupedstat.png) + + diff --git a/examples/simpletest_datastore_groupedstat/jkqtplotter_simpletest_datastore_groupedstat.cpp b/examples/simpletest_datastore_groupedstat/jkqtplotter_simpletest_datastore_groupedstat.cpp new file mode 100644 index 0000000000..7fa8cedf6e --- /dev/null +++ b/examples/simpletest_datastore_groupedstat/jkqtplotter_simpletest_datastore_groupedstat.cpp @@ -0,0 +1,265 @@ +/** \example jkqtplotter_simpletest_datastore_groupedstat.cpp + * Explains how to use the internal statistics library (see \ref jkqtptools_statistics ) together with JKQTPDatastore to generate grouped statistics (i.e. calculates errorbars or boxplots from groups of datapoints in a x/y-dataset). + * + * \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat + */ + +#include +#include "jkqtplotter/jkqtplotter.h" +#include "jkqtplotter/jkqtpgraphsscatter.h" +#include "jkqtplotter/jkqtpgraphsbarchart.h" +#include "jkqtplotter/jkqtpgraphsstatisticsadaptors.h" +#include "jkqtcommon/jkqtpstatisticstools.h" +#include "jkqtcommon/jkqtpstringtools.h" +#include +#include +#include + + +int main(int argc, char* argv[]) +{ + QApplication app(argc, argv); + + + // 1. create a window with several plotters and get a pointer to the internal datastores (for convenience) + QWidget mainWidget; + QGridLayout* lay; + mainWidget.setLayout(lay=new QGridLayout); + JKQTPlotter* plotbarchart=new JKQTPlotter(&mainWidget); + plotbarchart->getPlotter()->setPlotLabel("Barcharts"); + JKQTPDatastore* datastore1=plotbarchart->getDatastore(); + lay->addWidget(plotbarchart,0,0); + JKQTPlotter* plotboxplot=new JKQTPlotter(datastore1, &mainWidget); + plotboxplot->getPlotter()->setPlotLabel("Boxplots"); + lay->addWidget(plotboxplot,0,1); + JKQTPlotter* plotscattererrors=new JKQTPlotter(datastore1, &mainWidget); + plotscattererrors->getPlotter()->setPlotLabel("Scatter Plot with Error Indicators"); + lay->addWidget(plotscattererrors,0,2); + lay->setColumnStretch(0,1); + lay->setColumnStretch(1,1); + lay->setColumnStretch(2,2); + + + + // 2. Barcharts from categorized data: + // 2.1. First we generate a dataset, which is going to be used for a barchart + // The datapoints consist of pairs , where the groups are encoded + // by the numbers 1,2,3 and in each group, several measurements are taken + size_t colBarRawGroup=datastore1->addColumn("barchart, rawdata, group"); + size_t colBarRawValue=datastore1->addColumn("barchart, rawdata, value"); + + // data for group 1 + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 1, 1.1); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 1, 1.5); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 1, 0.8); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 1, 1.2); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 1, 1.4); + // data for group 2 + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 2, 2.2); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 2, 2.4); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 2, 1.9); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 2, 2.6); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 2, 2.1); + // data for group 3 + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 3, 4.1); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 3, 4.4); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 3, 3.8); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 3, 4.5); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 3, 3.7); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 3, 4.0); + // now some more datapoint, in mixed order + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 1, 0.9); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 2, 2.3); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 2, 2.0); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 1, 1.0); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 3, 4.2); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 1, 1.25); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 2, 2.35); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 3, 3.7); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 1, 0.75); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 2, 1.85); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 3, 4.5); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 1, 0.95); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 2, 1.65); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 3, 4.1); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 1, 1.15); + datastore1->appendToColumns(colBarRawGroup, colBarRawValue, 2, 2.15); + + + // 2.2. This dataset can be visualized with a simple scatter plot: + JKQTPXYLineGraph* gScatterForBar; + plotbarchart->addGraph(gScatterForBar=new JKQTPXYLineGraph(plotbarchart)); + gScatterForBar->setXYColumns(colBarRawGroup, colBarRawValue); + gScatterForBar->setDrawLine(false); + gScatterForBar->setSymbolType(JKQTPCross); + gScatterForBar->setSymbolSize(5); + gScatterForBar->setSymbolColor(QColorWithAlphaF(QColor("red"), 0.5)); + + // 2.3. Now we want to draw a barchart for every group, which indicates the + // average in each group. This is done using methods from the statistics + // library. + // First we need to group the data using jkqtpstatGroupData(), which assembles + // the data points in each group groupeddataBar + std::map > groupeddataBar; + jkqtpstatGroupData(datastore1->begin(colBarRawGroup), datastore1->end(colBarRawGroup), + datastore1->begin(colBarRawValue), datastore1->end(colBarRawValue), + groupeddataBar); + // now we can calculate the statistics for each group separately: + // Data is collected in two new columns + size_t colBarGroup=datastore1->addColumn("barchart, group"); + size_t colBarAverage=datastore1->addColumn("barchart, group-average"); + size_t colBarStdDev=datastore1->addColumn("barchart, group-stddev"); + // Statistics is calculated by simply iterating over groupeddataBar + // and calling functions like jkqtpstatAverage() for each group + for (auto it=groupeddataBar.begin(); it!=groupeddataBar.end(); ++it) { + datastore1->appendToColumn(colBarGroup, it->first); + datastore1->appendToColumn(colBarAverage, jkqtpstatAverage(it->second.begin(), it->second.end())); + datastore1->appendToColumn(colBarStdDev, jkqtpstatStdDev(it->second.begin(), it->second.end())); + } + + // 2.4. Finally the calculated groups are drawn + JKQTPBarVerticalErrorGraph* gBar; + plotbarchart->addGraph(gBar=new JKQTPBarVerticalErrorGraph(plotbarchart)); + gBar->setXYColumns(colBarGroup, colBarAverage); + gBar->setYErrorColumn(static_cast(colBarStdDev)); + + // 2.5. With the methods above we can also calculate more advanced statistics, like e.g. boxplots: + size_t colBarMedian=datastore1->addColumn("barchart, group-median"); + size_t colBarMin=datastore1->addColumn("barchart, group-min"); + size_t colBarMax=datastore1->addColumn("barchart, group-max"); + size_t colBarQ25=datastore1->addColumn("barchart, group-Q25"); + size_t colBarQ75=datastore1->addColumn("barchart, group-Q75"); + for (auto it=groupeddataBar.begin(); it!=groupeddataBar.end(); ++it) { + datastore1->appendToColumn(colBarMedian, jkqtpstatMedian(it->second.begin(), it->second.end())); + datastore1->appendToColumn(colBarMin, jkqtpstatMinimum(it->second.begin(), it->second.end())); + datastore1->appendToColumn(colBarMax, jkqtpstatMaximum(it->second.begin(), it->second.end())); + datastore1->appendToColumn(colBarQ25, jkqtpstatQuantile(it->second.begin(), it->second.end(), 0.25)); + datastore1->appendToColumn(colBarQ75, jkqtpstatQuantile(it->second.begin(), it->second.end(), 0.75)); + } + // 2.6. The result can be plotted using JKQTPBoxplotVerticalGraph, which receives a column for each value class of the final plot: + JKQTPBoxplotVerticalGraph* gBoxplot; + plotboxplot->addGraph(gBoxplot=new JKQTPBoxplotVerticalGraph(plotboxplot)); + gBoxplot->setPositionColumn(colBarGroup); + gBoxplot->setMinColumn(colBarMin); + gBoxplot->setMaxColumn(colBarMax); + gBoxplot->setMedianColumn(colBarMedian); + gBoxplot->setPercentile25Column(colBarQ25); + gBoxplot->setPercentile75Column(colBarQ75); + // 2.7. In order to safe yo the typing of the code above, shortcuts in the form of adaptors exist: + /* + jkqtpstatAddYErrorBarGraph(plotbarchart->getPlotter(), + datastore1->begin(colBarRawGroup), datastore1->end(colBarRawGroup), + datastore1->begin(colBarRawValue), datastore1->end(colBarRawValue)); + jkqtpstatAddHBoxplotsAndOutliers(plotboxplot->getPlotter(), + datastore1->begin(colBarRawGroup), datastore1->end(colBarRawGroup), + datastore1->begin(colBarRawValue), datastore1->end(colBarRawValue)); + */ + + + + + + // 3. Scatterplots from categorized data: + // 3.1. First we generate a second dataset, which is going to be used for a scaterplot + // The datapoints consist of pairs , that are based on a parabula with random + // deviations, both in x- and y-direction + size_t colScatterRawX=datastore1->addColumn("scatterplot, rawdata, x"); + size_t colScatterRawY=datastore1->addColumn("scatterplot, rawdata, y"); + std::random_device rd; // random number generators: + std::mt19937 gen{rd()}; + std::normal_distribution<> d1{0,0.5}; + const size_t N=100; + const double xmax=3.5; + for (size_t i=0; i(i)-static_cast(N)/2.0)*xmax/(static_cast(N)/2.0); + const double y=jkqtp_sqr(x)+2.0; + datastore1->appendToColumns(colScatterRawX, colScatterRawY, x+d1(gen), y+d1(gen)); + } + // 3.2. Now we can also add the raw dataset to the plot for visualization: + JKQTPXYParametrizedScatterGraph* gScatterRaw; + plotscattererrors->addGraph(gScatterRaw=new JKQTPXYParametrizedScatterGraph(plotscattererrors)); + gScatterRaw->setXYColumns(colScatterRawX, colScatterRawY); + gScatterRaw->setDrawLine(false); + gScatterRaw->setSymbolType(JKQTPCross); + gScatterRaw->setSymbolSize(5); + + // 3.3. Now we want to draw a scatterchart of the data, where data-points should be grouped + // together, in x-intervals of width 0.5. From all the points in each interval, we calculate the + // in both x- and y-direction the average and standard deviation. + // First we need to group the data using jkqtpstatGroupData(), which assembles + // the data points in each group groupeddataScatter. For the custom grouping of the datapoints + // we use the optional functor provided to jkqtpstatGroupData(): We use jkqtpstatGroupingCustomRound1D() + // with given parameters 0.25 for the (center) location of the first bin and bin width 0.5. The functor + // is not built by hand (which would be possible using std::bind), but with the generator function + // jkqtpstatMakeGroupingCustomRound1D(). + // in addition we use a variant of jkqtpstatGroupData(), which outputs a column with the category + // assigned to every data pair in the input data range + std::map,std::vector > > groupeddataScatter; + size_t colScatterRawGroup=datastore1->addColumn("scatterplot, rawdata, assigned-group"); + jkqtpstatGroupData(datastore1->begin(colScatterRawX), datastore1->end(colScatterRawX), + datastore1->begin(colScatterRawY), datastore1->end(colScatterRawY), + datastore1->backInserter(colScatterRawGroup), + groupeddataScatter, + jkqtpstatMakeGroupingCustomRound1D(0.25, 0.5)); + // The column colScatterRawGroup can now be used to color the scatter graph: + gScatterRaw->setColorColumn(colScatterRawGroup); + // now we can calculate the statistics for each group separately: + // Data is collected in two new columns + size_t colScatterXAvg=datastore1->addColumn("scatter, x, average"); + size_t colScatterXStd=datastore1->addColumn("scatter, x, stddev"); + size_t colScatterYAvg=datastore1->addColumn("scatter, y, average"); + size_t colScatterYStd=datastore1->addColumn("scatter, y, stddev"); + // Statistics is calculated by simply iterating over groupeddataScatter + // and calling functions like jkqtpstatAverage() for each group + for (auto it=groupeddataScatter.begin(); it!=groupeddataScatter.end(); ++it) { + datastore1->appendToColumn(colScatterXAvg, jkqtpstatAverage(it->second.first.begin(), it->second.first.end())); + datastore1->appendToColumn(colScatterXStd, jkqtpstatStdDev(it->second.first.begin(), it->second.first.end())); + datastore1->appendToColumn(colScatterYAvg, jkqtpstatAverage(it->second.second.begin(), it->second.second.end())); + datastore1->appendToColumn(colScatterYStd, jkqtpstatStdDev(it->second.second.begin(), it->second.second.end())); + } + + // 3.4. Finally the calculated groups are drawn + JKQTPXYLineErrorGraph* gScatterErr; + plotscattererrors->addGraph(gScatterErr=new JKQTPXYLineErrorGraph(plotscattererrors)); + gScatterErr->setXYColumns(colScatterXAvg, colScatterYAvg); + gScatterErr->setXErrorColumn(static_cast(colScatterXStd)); + gScatterErr->setYErrorColumn(static_cast(colScatterYStd)); + gScatterErr->setSymbolType(JKQTPFilledTriangle); + gScatterErr->setDrawLine(false); + + // 3.5. also here an adaptor exists, which makes the task easier: + /* + jkqtpstatAddXYErrorLineGraph(plotscattererrors->getPlotter(), + datastore1->begin(colScatterRawX), datastore1->end(colScatterRawX), + datastore1->begin(colScatterRawY), datastore1->end(colScatterRawY), + jkqtpstatMakeGroupingCustomRound1D(0.25, 0.5)); + */ + + + + + // autoscale the plot so the graph is contained + plotboxplot->synchronizeToMaster(plotbarchart, JKQTBasePlotter::sdXYAxes); + plotboxplot->zoomToFit(); + plotboxplot->setGrid(false); + plotboxplot->setShowZeroAxes(false); + plotboxplot->getPlotter()->setKeyBackgroundColor(QColorWithAlphaF("white", 0.25), Qt::SolidPattern); + plotbarchart->setAbsoluteY(0,5); + plotboxplot->setAbsoluteY(0,5); + plotbarchart->zoomToFit(); + plotbarchart->setGrid(false); + plotbarchart->setShowZeroAxes(false); + plotbarchart->getPlotter()->setKeyBackgroundColor(QColorWithAlphaF("white", 0.25), Qt::SolidPattern); + plotbarchart->moveGraphTop(gScatterForBar); + plotscattererrors->zoomToFit(); + plotscattererrors->setGrid(false); + plotscattererrors->setShowZeroAxes(false); + plotscattererrors->getPlotter()->setKeyBackgroundColor(QColorWithAlphaF("white", 0.25), Qt::SolidPattern); + + + // show plotter and make it a decent size + mainWidget.show(); + mainWidget.resize(1200,400); + + return app.exec(); +} diff --git a/examples/simpletest_datastore_groupedstat/jkqtplotter_simpletest_datastore_groupedstat.pro b/examples/simpletest_datastore_groupedstat/jkqtplotter_simpletest_datastore_groupedstat.pro new file mode 100644 index 0000000000..817ebf4752 --- /dev/null +++ b/examples/simpletest_datastore_groupedstat/jkqtplotter_simpletest_datastore_groupedstat.pro @@ -0,0 +1,27 @@ +# source code for this simple demo +SOURCES = jkqtplotter_simpletest_datastore_groupedstat.cpp + +# configure Qt +CONFIG += link_prl qt +QT += core gui xml svg +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport + +# output executable name +TARGET = jkqtplotter_simpletest_datastore_groupedstat + +# include JKQTPlotter source headers and link against library +DEPENDPATH += ../../lib ../../staticlib/jkqtplotterlib +INCLUDEPATH += ../../lib +CONFIG (debug, debug|release) { + LIBS += -L../../staticlib/jkqtplotterlib/debug -ljkqtplotterlib_debug +} else { + LIBS += -L../../staticlib/jkqtplotterlib/release -ljkqtplotterlib +} +message("LIBS = $$LIBS") + +win32-msvc*: DEFINES += _USE_MATH_DEFINES +win32-msvc*: DEFINES += NOMINMAX + + + + diff --git a/examples/simpletest_datastore_groupedstat/jkqtplotter_simpletest_datastore_groupedstat_and_lib.pro b/examples/simpletest_datastore_groupedstat/jkqtplotter_simpletest_datastore_groupedstat_and_lib.pro new file mode 100644 index 0000000000..f3d7e69339 --- /dev/null +++ b/examples/simpletest_datastore_groupedstat/jkqtplotter_simpletest_datastore_groupedstat_and_lib.pro @@ -0,0 +1,8 @@ +TEMPLATE = subdirs + +SUBDIRS += jkqtplotterlib jkqtplotter_simpletest_datastore_groupedstat + +jkqtplotterlib.file = ../../staticlib/jkqtplotterlib/jkqtplotterlib.pro + +jkqtplotter_simpletest_datastore_groupedstat.file=$$PWD/jkqtplotter_simpletest_datastore_groupedstat.pro +jkqtplotter_simpletest_datastore_groupedstat.depends = jkqtplotterlib diff --git a/examples/simpletest_datastore_iterators/README.md b/examples/simpletest_datastore_iterators/README.md index e9d7f6537e..407f5e0e25 100644 --- a/examples/simpletest_datastore_iterators/README.md +++ b/examples/simpletest_datastore_iterators/README.md @@ -1,10 +1,10 @@ # Tutorial (JKQTPDatastore): Iterator-Based usage of JKQTPDatastore {#JKQTPlotterBasicJKQTPDatastoreIterators} - [JKQTPlotterBasicJKQTPDatastore]: @ref JKQTPlotterBasicJKQTPDatastore "Basic Usage of JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreIterators]: @ref JKQTPlotterBasicJKQTPDatastoreIterators "Iterator-Based usage of JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreStatistics]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics "Advanced 1-Dimensional Statistics with JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreRegression]: @ref JKQTPlotterBasicJKQTPDatastoreRegression "Regression Analysis (with the Statistics Library)" +[JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat]: @ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat "1-Dimensional Group Statistics with JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreStatistics2D]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics2D "Advanced 2-Dimensional Statistics with JKQTPDatastore" [statisticslibrary]: @ref jkqtptools_math_statistics "JKQTPlotter Statistics Library" @@ -14,8 +14,10 @@ This tutorial project (see `./examples/simpletest_datastore_iterators/`) explain - [JKQTPlotterBasicJKQTPDatastore] - [JKQTPlotterBasicJKQTPDatastoreIterators] - [JKQTPlotterBasicJKQTPDatastoreStatistics] - - [JKQTPlotterBasicJKQTPDatastoreStatistics2D] - [JKQTPlotterBasicJKQTPDatastoreRegression] + - [JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat] + - [JKQTPlotterBasicJKQTPDatastoreStatistics2D] + diff --git a/examples/simpletest_datastore_regression/README.md b/examples/simpletest_datastore_regression/README.md index 4a98a9a1b3..d7d2aab14c 100644 --- a/examples/simpletest_datastore_regression/README.md +++ b/examples/simpletest_datastore_regression/README.md @@ -4,18 +4,19 @@ [JKQTPlotterBasicJKQTPDatastoreIterators]: @ref JKQTPlotterBasicJKQTPDatastoreIterators "Iterator-Based usage of JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreStatistics]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics "Advanced 1-Dimensional Statistics with JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreRegression]: @ref JKQTPlotterBasicJKQTPDatastoreRegression "Regression Analysis (with the Statistics Library)" +[JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat]: @ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat "1-Dimensional Group Statistics with JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreStatistics2D]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics2D "Advanced 2-Dimensional Statistics with JKQTPDatastore" [statisticslibrary]: @ref jkqtptools_math_statistics "JKQTPlotter Statistics Library" - This tutorial project (see `./examples/simpletest_datastore_statistics/`) explains several advanced functions of JKQTPDatastore in combination with the [[statisticslibrary]] conatined in JKQTPlotter. ***Note*** that there are additional tutorial explaining other aspects of data mangement in JKQTPDatastore: - [JKQTPlotterBasicJKQTPDatastore] - [JKQTPlotterBasicJKQTPDatastoreIterators] - [JKQTPlotterBasicJKQTPDatastoreStatistics] - - [JKQTPlotterBasicJKQTPDatastoreStatistics2D] - [JKQTPlotterBasicJKQTPDatastoreRegression] + - [JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat] + - [JKQTPlotterBasicJKQTPDatastoreStatistics2D] [TOC] diff --git a/examples/simpletest_datastore_statistics/README.md b/examples/simpletest_datastore_statistics/README.md index 1addbfbb48..1bacdbb887 100644 --- a/examples/simpletest_datastore_statistics/README.md +++ b/examples/simpletest_datastore_statistics/README.md @@ -1,22 +1,22 @@ # Tutorial (JKQTPDatastore): Advanced 1-Dimensional Statistics with JKQTPDatastore {#JKQTPlotterBasicJKQTPDatastoreStatistics} - [JKQTPlotterBasicJKQTPDatastore]: @ref JKQTPlotterBasicJKQTPDatastore "Basic Usage of JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreIterators]: @ref JKQTPlotterBasicJKQTPDatastoreIterators "Iterator-Based usage of JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreStatistics]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics "Advanced 1-Dimensional Statistics with JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreRegression]: @ref JKQTPlotterBasicJKQTPDatastoreRegression "Regression Analysis (with the Statistics Library)" +[JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat]: @ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat "1-Dimensional Group Statistics with JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreStatistics2D]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics2D "Advanced 2-Dimensional Statistics with JKQTPDatastore" [statisticslibrary]: @ref jkqtptools_math_statistics "JKQTPlotter Statistics Library" - This tutorial project (see `./examples/simpletest_datastore_statistics/`) explains several advanced functions of JKQTPDatastore in combination with the [[statisticslibrary]] conatined in JKQTPlotter. ***Note*** that there are additional tutorial explaining other aspects of data mangement in JKQTPDatastore: - [JKQTPlotterBasicJKQTPDatastore] - [JKQTPlotterBasicJKQTPDatastoreIterators] - [JKQTPlotterBasicJKQTPDatastoreStatistics] - - [JKQTPlotterBasicJKQTPDatastoreStatistics2D] - [JKQTPlotterBasicJKQTPDatastoreRegression] + - [JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat] + - [JKQTPlotterBasicJKQTPDatastoreStatistics2D] [TOC] diff --git a/examples/simpletest_datastore_statistics_2d/README.md b/examples/simpletest_datastore_statistics_2d/README.md index 5007a28edd..124ba0d450 100644 --- a/examples/simpletest_datastore_statistics_2d/README.md +++ b/examples/simpletest_datastore_statistics_2d/README.md @@ -1,22 +1,22 @@ # Tutorial (JKQTPDatastore): Advanced 2-Dimensional Statistics with JKQTPDatastore {#JKQTPlotterBasicJKQTPDatastoreStatistics2D} - [JKQTPlotterBasicJKQTPDatastore]: @ref JKQTPlotterBasicJKQTPDatastore "Basic Usage of JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreIterators]: @ref JKQTPlotterBasicJKQTPDatastoreIterators "Iterator-Based usage of JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreStatistics]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics "Advanced 1-Dimensional Statistics with JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreRegression]: @ref JKQTPlotterBasicJKQTPDatastoreRegression "Regression Analysis (with the Statistics Library)" +[JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat]: @ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat "1-Dimensional Group Statistics with JKQTPDatastore" [JKQTPlotterBasicJKQTPDatastoreStatistics2D]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics2D "Advanced 2-Dimensional Statistics with JKQTPDatastore" [statisticslibrary]: @ref jkqtptools_math_statistics "JKQTPlotter Statistics Library" - This tutorial project (see `./examples/simpletest_datastore_statistics_2d/`) explains several advanced functions of JKQTPDatastore in combination with the [[statisticslibrary]] conatined in JKQTPlotter. ***Note*** that there are additional tutorial explaining other aspects of data mangement in JKQTPDatastore: - [JKQTPlotterBasicJKQTPDatastore] - [JKQTPlotterBasicJKQTPDatastoreIterators] - [JKQTPlotterBasicJKQTPDatastoreStatistics] - - [JKQTPlotterBasicJKQTPDatastoreStatistics2D] - [JKQTPlotterBasicJKQTPDatastoreRegression] + - [JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat] + - [JKQTPlotterBasicJKQTPDatastoreStatistics2D] [TOC] diff --git a/examples/simpletest_errorbarstyles/README.md b/examples/simpletest_errorbarstyles/README.md index e8d28528a1..5ab4aa8ba7 100644 --- a/examples/simpletest_errorbarstyles/README.md +++ b/examples/simpletest_errorbarstyles/README.md @@ -1,6 +1,11 @@ # Example (JKQTPlotter): Different Types of Errorindicators {#JKQTPlotterErrorBarStyles} This project (see `./examples/simpletest_errorbarstyles/`) simply creates a JKQTPlotter widget (as a new window) and adds several curves show-casing different styles of error indicators. Data is initialized from two QVector objects. +[JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat]: @ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat "1-Dimensional Group Statistics with JKQTPDatastore" +[statisticslibrary]: @ref jkqtptools_math_statistics "JKQTPlotter Statistics Library" + +***Note:*** This examples explains how to plot graphs with error indicators, when the data has already been calculated. The tutorial [JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat] explains one way how to use the [statisticslibrary] in order to calculate the errors from data. + The source code of the main application can be found in [`jkqtplotter_simpletest_errorbarstyles.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_errorbarstyles/jkqtplotter_simpletest_errorbarstyles.cpp). First some data is added to the internal datastore (mostly, like explained in several other examples, like e.g. [Line Graph with Different Symbols and Line Styles](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_symbols_and_styles)). The (in a loop) several graphs are added, each with a distinct style for its error indicators: diff --git a/examples/test_distributionplot/README.md b/examples/test_distributionplot/README.md index ffaca77491..c833b9b974 100644 --- a/examples/test_distributionplot/README.md +++ b/examples/test_distributionplot/README.md @@ -1,6 +1,19 @@ # Example (JKQTPlotter): Plotting a Statistical Distribution of Data {#JKQTPlotterDistributionPlot} This project (see [`test_distributionplot`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/test_distributionplot) demonstrates how to combine several different graphs and geometric elements to show a set of random values and their statistics. + +[JKQTPlotterBasicJKQTPDatastore]: @ref JKQTPlotterBasicJKQTPDatastore "Basic Usage of JKQTPDatastore" +[JKQTPlotterBasicJKQTPDatastoreIterators]: @ref JKQTPlotterBasicJKQTPDatastoreIterators "Iterator-Based usage of JKQTPDatastore" +[JKQTPlotterBasicJKQTPDatastoreStatistics]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics "Advanced 1-Dimensional Statistics with JKQTPDatastore" +[JKQTPlotterBasicJKQTPDatastoreRegression]: @ref JKQTPlotterBasicJKQTPDatastoreRegression "Regression Analysis (with the Statistics Library)" +[JKQTPlotterBasicJKQTPDatastoreStatistics2D]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics2D "Advanced 2-Dimensional Statistics with JKQTPDatastore" +[statisticslibrary]: @ref jkqtptools_math_statistics "JKQTPlotter Statistics Library" +[JKQTPlotterBoxplotStyling]: @ref JKQTPlotterBoxplotStyling "Styling different aspects of boxplots" +[JKQTPlotterBoxplotsGraphs]: @ref JKQTPlotterBoxplotsGraphs "Boxplots" + +***Note*** that this example explains how to generate the statistics plots by hand, i.e. by calculating all the statistical properties for the boxplots and then adding the necessary graphs. The internal [statisticslibrary] offers methods to perform these calculations, which are explained in the tutorial [JKQTPlotterBasicJKQTPDatastoreStatistics] in detail. Several examples give more details on boxplots: [JKQTPlotterBoxplotsGraphs], [JKQTPlotterBoxplotStyling]. + + The source code of the main application is (see [`test_distributionplot.cpp`](test_distributionplot.cpp). After adding all necessary data to the JKQTDatastore: diff --git a/examples/test_styledboxplot/README.md b/examples/test_styledboxplot/README.md index 6b967df6fe..0c8a782e64 100644 --- a/examples/test_styledboxplot/README.md +++ b/examples/test_styledboxplot/README.md @@ -1,6 +1,19 @@ # Example (JKQTPlotter): Styling different aspects of boxplots {#JKQTPlotterBoxplotStyling} This project (see [`test_styledboxplot`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/test_styledboxplot) demonstrates how to style different aspects of boxplots and how to draw different types and styles of boxplots. For a simple introduction into how to use boxplots, see [Plotting Box Plots](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_boxplot) and [Plotting a Statistical Distribution of Data](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/test_distributionplot). +[JKQTPlotterBasicJKQTPDatastore]: @ref JKQTPlotterBasicJKQTPDatastore "Basic Usage of JKQTPDatastore" +[JKQTPlotterBasicJKQTPDatastoreIterators]: @ref JKQTPlotterBasicJKQTPDatastoreIterators "Iterator-Based usage of JKQTPDatastore" +[JKQTPlotterBasicJKQTPDatastoreStatistics]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics "Advanced 1-Dimensional Statistics with JKQTPDatastore" +[JKQTPlotterBasicJKQTPDatastoreRegression]: @ref JKQTPlotterBasicJKQTPDatastoreRegression "Regression Analysis (with the Statistics Library)" +[JKQTPlotterBasicJKQTPDatastoreStatistics2D]: @ref JKQTPlotterBasicJKQTPDatastoreStatistics2D "Advanced 2-Dimensional Statistics with JKQTPDatastore" +[statisticslibrary]: @ref jkqtptools_math_statistics "JKQTPlotter Statistics Library" +[JKQTPlotterBoxplotStyling]: @ref JKQTPlotterBoxplotStyling "Styling different aspects of boxplots" +[JKQTPlotterBoxplotsGraphs]: @ref JKQTPlotterBoxplotsGraphs "Boxplots" + +***Note*** that this example explains how to style boxplots. The example [JKQTPlotterBoxplotsGraphs] explains basics of how to create boxplots. The internal [statisticslibrary] offers methods to calculate the statistical properties necessary for boxplots, which is explained in the tutorial [JKQTPlotterBasicJKQTPDatastoreStatistics] in detail. + + + The link http://vita.had.co.nz/papers/boxplots.pdf leads to a paper that described the history and different types of boxplots. The source code of the main application can be found in [`test_styledboxplot.cpp`](test_styledboxplot.cpp). diff --git a/lib/jkqtcommon/jkqtpstatbasics.h b/lib/jkqtcommon/jkqtpstatbasics.h index 4021f38220..9ecf319ccd 100644 --- a/lib/jkqtcommon/jkqtpstatbasics.h +++ b/lib/jkqtcommon/jkqtpstatbasics.h @@ -40,9 +40,6 @@ #include "jkqtcommon/jkqtpdebuggingtools.h" - - - /*! \brief calculates the average of a given data range \a first ... \a last \ingroup jkqtptools_math_statistics_basic @@ -78,6 +75,8 @@ inline double jkqtpstatAverage(InputIt first, InputIt last, size_t* Noutput=null + + /*! \brief calculates the weighted average of a given data range \a first ... \a last \ingroup jkqtptools_math_statistics_basic diff --git a/lib/jkqtcommon/jkqtpstatisticstools.cpp b/lib/jkqtcommon/jkqtpstatgrouped.cpp similarity index 58% rename from lib/jkqtcommon/jkqtpstatisticstools.cpp rename to lib/jkqtcommon/jkqtpstatgrouped.cpp index d9fccf079c..422ad0eadf 100644 --- a/lib/jkqtcommon/jkqtpstatisticstools.cpp +++ b/lib/jkqtcommon/jkqtpstatgrouped.cpp @@ -19,4 +19,22 @@ -#include "jkqtpstatisticstools.h" +#include "jkqtpstatgrouped.h" + +double jkqtpstatGroupingIdentity1D(double v) { + return v; +} + +double jkqtpstatGroupingRound1D(double v) { + return round(v); +} + +double jkqtpstatGroupingCustomRound1D(double v, double firstGroupCenter, double groupWidth) { + return round((v-firstGroupCenter)/(2.0*groupWidth)); +} + + +JKQTPStatGroupDefinitionFunctor1D jkqtpstatMakeGroupingCustomRound1D(double firstGroupCenter, double groupWidth) +{ + return std::bind(&jkqtpstatGroupingCustomRound1D, std::placeholders::_1, firstGroupCenter, groupWidth); +} diff --git a/lib/jkqtcommon/jkqtpstatgrouped.h b/lib/jkqtcommon/jkqtpstatgrouped.h new file mode 100644 index 0000000000..4009a15e40 --- /dev/null +++ b/lib/jkqtcommon/jkqtpstatgrouped.h @@ -0,0 +1,237 @@ +/* + Copyright (c) 2008-2019 Jan W. Krieger () + + last modification: $LastChangedDate$ (revision $Rev$) + + 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 + the Free Software Foundation, either version 2.1 of the License, or + (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 . +*/ + + +#ifndef JKQTPSTATGROUPED_H_INCLUDED +#define JKQTPSTATGROUPED_H_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "jkqtcommon/jkqtp_imexport.h" +#include "jkqtcommon/jkqtplinalgtools.h" +#include "jkqtcommon/jkqtparraytools.h" +#include "jkqtcommon/jkqtpdebuggingtools.h" +#include "jkqtcommon/jkqtpstatbasics.h" + +/*! \brief a functor \f$ f(x): \mathbb{R}\rightarrow\mathbb{R} \f$ which assignes a value \f$ x \f$ to a group center \f$ f(x) \f$ + \ingroup jkqtptools_math_statistics_grouped + + The simplest version are e.g. + - jkqtpstatGroupingIdentity1D() + - jkqtpstatGroupingRound1D() + - jkqtpstatGroupingCustomRound1D() + . + + \see jkqtpstatGroupData +*/ +typedef std::function JKQTPStatGroupDefinitionFunctor1D; + + + +/*! \brief use a column value as group ID directly + \ingroup jkqtptools_math_statistics_grouped + + \see JKQTPStatGroupDefinitionFunctor1D +*/ +double jkqtpstatGroupingIdentity1D(double v); +/*! \brief use a rounded column value as group ID directly \f$ f(x)=\mbox{round}(x) \f$ + \ingroup jkqtptools_math_statistics_grouped + + \see JKQTPStatGroupDefinitionFunctor1D +*/ +double jkqtpstatGroupingRound1D(double v); +/*! \brief assign each value to groups \f$ \mbox{firstGroupCenter}, \mbox{firstGroupCenter}\pm\mbox{groupWidth}/2, \mbox{firstGroupCenter}\pm2\cdot\mbox{groupWidth}/2, , \mbox{firstGroupCenter}\pm3\cdot\mbox{groupWidth}/2, ... \f$ + \ingroup jkqtptools_math_statistics_grouped + + This is equivalent to \f$ \mbox{round}\left(\frac{x-\mbox{firstGroupCenter}}{\mbox{groupWidth}/2}\right) \f$ + + \see JKQTPStatGroupDefinitionFunctor1D, jkqtpstatMakeGroupingCustomRound1D() for a factory-function that returns a functor of this function bound to specific arguments. +*/ +double jkqtpstatGroupingCustomRound1D(double v, double firstGroupCenter, double groupWidth); +/*! \brief generates a functor of jkqtpstatGroupingCustomRound1D() with the two paramaters \a firstGroupCenter and \a groupWidth fixed to the given values + \ingroup jkqtptools_math_statistics_grouped + + This is equivalent to \c std::bind(&jkqtpstatGroupingCustomRound1D,std::placeholders::_1,firstGroupCenter,groupWidth); + + \see JKQTPStatGroupDefinitionFunctor1D, jkqtpstatGroupingCustomRound1D() +*/ +JKQTPStatGroupDefinitionFunctor1D jkqtpstatMakeGroupingCustomRound1D(double firstGroupCenter, double groupWidth); + + + +/*! \brief groups data from an input range \a inFirstCat / \a inFirstValue ... \a inLastCat / \a outFirstCat representing pairs \f$ (c_i,v_i) \f$ of a + category value \f$ c_i \f$ and a group value \f$ v_i \f$ into groups \f$ V_j=\{v_{i}|c_i\equiv c_{\text{out},j}\} \f$ of data that were assigned + to the same group, i.e. \f$ c_i\equiv c_{\text{out},j} \f$ . A functor \a groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \ingroup jkqtptools_math_statistics_grouped + + \tparam InputCatIt standard iterator type of \a inFirstCat and \a inLastCat + \tparam InputValueIt standard iterator type of \a inFirstValue and \a inLastValue + \param inFirstCat iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ + \param inLastCat iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ + \param inFirstValue iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ + \param inLastValue iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ + \param[out] groupeddata receives the grouped data, each key in the map represents one group, each map-value contains a vector with the value data + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + + \note the contents of \a groupeddata is not cleared before usage, so you can also use this fucntion to append to a group! + + \see JKQTPStatGroupDefinitionFunctor1D, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline void jkqtpstatGroupData(InputCatIt inFirstCat, InputCatIt inLastCat, InputValueIt inFirstValue, InputValueIt inLastValue, std::map >& groupeddata, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D) { + auto inCat=inFirstCat; + auto inVal=inFirstValue; + for (; inCat!=inLastCat && inVal!=inLastValue; ++inCat, ++inVal) { + const double c=jkqtp_todouble(*inCat); + const double v=jkqtp_todouble(*inVal); + if (JKQTPIsOKFloat(c) && JKQTPIsOKFloat(v)) { + const double g=groupDefFunc(c); + groupeddata[g].push_back(v); + } + } +} + +/*! \brief groups data from an input range \a inFirstCat / \a inFirstValue ... \a inLastCat / \a outFirstCat representing pairs \f$ (c_i,v_i) \f$ of a + category value \f$ c_i \f$ and a group value \f$ v_i \f$ into groups \f$ V_j=\{v_{i}|c_i\equiv c_{\text{out},j}\} \f$ of data that were assigned + to the same group, i.e. \f$ c_i\equiv c_{\text{out},j} \f$ . A functor \a groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \ingroup jkqtptools_math_statistics_grouped + + \tparam InputCatIt standard iterator type of \a inFirstCat and \a inLastCat + \tparam InputValueIt standard iterator type of \a inFirstValue and \a inLastValue + \tparam OutputGroupIt standard output iterator type of \a outFirstCategory + \param inFirstCat iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ + \param inLastCat iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ + \param inFirstValue iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ + \param inLastValue iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ + \param[out] outFirstCategory for each element in the range \a inFirstCat / \a inFirstValue ... \a inLastCat / \a outFirstCat this receives the calculated category + \param[out] groupeddata receives the grouped data, each key in the map represents one group, each map-value contains a vector with the value data + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + + \note the contents of \a groupeddata is not cleared before usage, so you can also use this fucntion to append to a group! + + \see JKQTPStatGroupDefinitionFunctor1D, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline void jkqtpstatGroupData(InputCatIt inFirstCat, InputCatIt inLastCat, InputValueIt inFirstValue, InputValueIt inLastValue, OutputGroupIt outFirstCategory, std::map >& groupeddata, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D) { + auto inCat=inFirstCat; + auto inVal=inFirstValue; + auto outCat=outFirstCategory; + for (; inCat!=inLastCat && inVal!=inLastValue; ++inCat, ++inVal) { + const double c=jkqtp_todouble(*inCat); + const double v=jkqtp_todouble(*inVal); + if (JKQTPIsOKFloat(c) && JKQTPIsOKFloat(v)) { + const double g=groupDefFunc(c); + groupeddata[g].push_back(v); + *outCat=g; + } else { + *outCat=JKQTP_DOUBLE_NAN; + } + ++outCat; + } +} + + +/*! \brief groups data from an input range \a inFirstCat / \a inFirstValue ... \a inLastCat / \a outFirstCat representing pairs \f$ (c_i,v_i) \f$ of a + category value \f$ c_i \f$ and a group value \f$ v_i \f$ into groups \f$ V_j=\{v_{i}|c_i\equiv c_{\text{out},j}\} \f$ of data that were assigned + to the same group, i.e. \f$ c_i\equiv c_{\text{out},j} \f$ . A functor \a groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \ingroup jkqtptools_math_statistics_grouped + + \tparam InputCatIt standard iterator type of \a inFirstCat and \a inLastCat + \tparam InputValueIt standard iterator type of \a inFirstValue and \a inLastValue + \param inFirstCat iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ + \param inLastCat iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ + \param inFirstValue iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ + \param inLastValue iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ + \param[out] groupeddata receives the grouped data, each key in the map represents one group, each map-value contains two vecors with the category and value data respectively + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + + \note the contents of \a groupeddata is not cleared before usage, so you can also use this fucntion to append to a group! + + \see JKQTPStatGroupDefinitionFunctor1D, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline void jkqtpstatGroupData(InputCatIt inFirstCat, InputCatIt inLastCat, InputValueIt inFirstValue, InputValueIt inLastValue, std::map,std::vector > >& groupeddata, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D) { + auto inCat=inFirstCat; + auto inVal=inFirstValue; + for (; inCat!=inLastCat && inVal!=inLastValue; ++inCat, ++inVal) { + const double c=jkqtp_todouble(*inCat); + const double v=jkqtp_todouble(*inVal); + if (JKQTPIsOKFloat(c) && JKQTPIsOKFloat(v)) { + const double g=groupDefFunc(c); + groupeddata[g].first.push_back(c); + groupeddata[g].second.push_back(v); + } + } +} + + +/*! \brief groups data from an input range \a inFirstCat / \a inFirstValue ... \a inLastCat / \a outFirstCat representing pairs \f$ (c_i,v_i) \f$ of a + category value \f$ c_i \f$ and a group value \f$ v_i \f$ into groups \f$ V_j=\{v_{i}|c_i\equiv c_{\text{out},j}\} \f$ of data that were assigned + to the same group, i.e. \f$ c_i\equiv c_{\text{out},j} \f$ . A functor \a groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \ingroup jkqtptools_math_statistics_grouped + + \tparam InputCatIt standard iterator type of \a inFirstCat and \a inLastCat + \tparam InputValueIt standard iterator type of \a inFirstValue and \a inLastValue + \tparam OutputGroupIt standard output iterator type of \a outFirstCategory + \param inFirstCat iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ + \param inLastCat iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ + \param inFirstValue iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ + \param inLastValue iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ + \param[out] outFirstCategory for each element in the range \a inFirstCat / \a inFirstValue ... \a inLastCat / \a outFirstCat this receives the calculated category + \param[out] groupeddata receives the grouped data, each key in the map represents one group, each map-value contains two vecors with the category and value data respectively + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + + \note the contents of \a groupeddata is not cleared before usage, so you can also use this fucntion to append to a group! + + \see JKQTPStatGroupDefinitionFunctor1D, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline void jkqtpstatGroupData(InputCatIt inFirstCat, InputCatIt inLastCat, InputValueIt inFirstValue, InputValueIt inLastValue, OutputGroupIt outFirstCategory, std::map,std::vector > >& groupeddata, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D) { + auto inCat=inFirstCat; + auto inVal=inFirstValue; + auto outCat=outFirstCategory; + for (; inCat!=inLastCat && inVal!=inLastValue; ++inCat, ++inVal) { + const double c=jkqtp_todouble(*inCat); + const double v=jkqtp_todouble(*inVal); + if (JKQTPIsOKFloat(c) && JKQTPIsOKFloat(v)) { + const double g=groupDefFunc(c); + groupeddata[g].first.push_back(c); + groupeddata[g].second.push_back(v); + *outCat=g; + } else { + *outCat=JKQTP_DOUBLE_NAN; + } + ++outCat; + } +} + +#endif // JKQTPSTATGROUPED_H_INCLUDED + + diff --git a/lib/jkqtcommon/jkqtpstatisticstools.h b/lib/jkqtcommon/jkqtpstatisticstools.h index 3469177546..bc2f4527c0 100644 --- a/lib/jkqtcommon/jkqtpstatisticstools.h +++ b/lib/jkqtcommon/jkqtpstatisticstools.h @@ -27,6 +27,7 @@ #include "jkqtcommon/jkqtpstatkde.h" #include "jkqtcommon/jkqtpstatpoly.h" #include "jkqtcommon/jkqtpstatregression.h" +#include "jkqtcommon/jkqtpstatgrouped.h" #endif // JKQTPSTATISTICSTOOLS_H_INCLUDED diff --git a/lib/jkqtcommon/jkqtpstatpoly.h b/lib/jkqtcommon/jkqtpstatpoly.h index c2186918d1..d5f0774793 100644 --- a/lib/jkqtcommon/jkqtpstatpoly.h +++ b/lib/jkqtcommon/jkqtpstatpoly.h @@ -46,7 +46,6 @@ /*! \brief fits (in a least-squares sense) a polynomial \f$ f(x)=\sum\limits_{i=0}^Pp_ix^i \f$ of order P to a set of N data pairs \f$ (x_i,y_i) \f$ \ingroup jkqtptools_math_statistics_poly - \ingroup jkqtptools_math_statistics_regression \tparam InputItX standard iterator type of \a firstX and \a lastX. \tparam InputItY standard iterator type of \a firstY and \a lastY. diff --git a/lib/jkqtpcommon.pri b/lib/jkqtpcommon.pri index 694a89ba68..e13646c465 100644 --- a/lib/jkqtpcommon.pri +++ b/lib/jkqtpcommon.pri @@ -35,7 +35,9 @@ isEmpty(JKQTP_COMMON_PRI_INCLUDED) { $$PWD/jkqtcommon/jkqtpstathistogram.h \ $$PWD/jkqtcommon/jkqtpstatkde.h \ $$PWD/jkqtcommon/jkqtpstatregression.h \ - $$PWD/jkqtcommon/jkqtpstatpoly.h + $$PWD/jkqtcommon/jkqtpstatpoly.h \ + $$PWD/jkqtcommon/jkqtpstatgrouped.h + SOURCES += $$PWD/jkqtcommon/jkqtpdebuggingtools.cpp \ @@ -51,12 +53,12 @@ isEmpty(JKQTP_COMMON_PRI_INCLUDED) { $$PWD/jkqtcommon/jkqtpmathparser.cpp \ $$PWD/jkqtcommon/jkqttools.cpp \ $$PWD/jkqtcommon/jkqtparraytools.cpp \ - $$PWD/jkqtcommon/jkqtpstatisticstools.cpp \ $$PWD/jkqtcommon/jkqtpstatbasics.cpp \ $$PWD/jkqtcommon/jkqtpstathistogram.cpp \ $$PWD/jkqtcommon/jkqtpstatkde.cpp \ $$PWD/jkqtcommon/jkqtpstatregression.cpp \ - $$PWD/jkqtcommon/jkqtpstatpoly.cpp + $$PWD/jkqtcommon/jkqtpstatpoly.cpp \ + $$PWD/jkqtcommon/jkqtpstatgrouped.cpp INCLUDEPATH += $$PWD diff --git a/lib/jkqtplotter/jkqtpgraphsbarchart.h b/lib/jkqtplotter/jkqtpgraphsbarchart.h index ae64ac2daa..dd439061f0 100644 --- a/lib/jkqtplotter/jkqtpgraphsbarchart.h +++ b/lib/jkqtplotter/jkqtpgraphsbarchart.h @@ -54,7 +54,7 @@ You can use JKQTPlotter::addHorizontalBargraph() to add a series of bargraphs, where the width and shift are determined automatically. The y-columns are given as a QVector to this function. - + \see JKQTPBarHorizontalGraph, \ref JKQTPlotterBarcharts, jkqtpstatAddHHistogram1D(), jkqtpstatAddHHistogram1DAutoranged() */ class JKQTP_LIB_EXPORT JKQTPBarVerticalGraph: public JKQTPXYGraph, public JKQTPGraphLineStyleMixin, public JKQTPGraphFillStyleMixin { Q_OBJECT @@ -173,6 +173,7 @@ class JKQTP_LIB_EXPORT JKQTPBarVerticalGraph: public JKQTPXYGraph, public JKQTPG * Draw stacked barcharts by connecting several plots by calling \c setStackedParent(belowPlot) for each plot * \image html JKQTPBarVerticalGraphStacked.png * + * \see JKQTPBarVerticalGraph, \ref JKQTPlotterStackedBarChart */ class JKQTP_LIB_EXPORT JKQTPBarVerticalStackableGraph: public JKQTPBarVerticalGraph { Q_OBJECT @@ -212,6 +213,7 @@ class JKQTP_LIB_EXPORT JKQTPBarVerticalStackableGraph: public JKQTPBarVerticalGr * This works much the same as JKQTPBarHorizontalGraph. Here is an example output: * \image html plot_bargraphverploterr.png * + * \see jkqtpstatAddYErrorBarGraph(), JKQTPBarVerticalGraph, \ref JKQTPlotterBarcharts */ class JKQTP_LIB_EXPORT JKQTPBarVerticalErrorGraph: public JKQTPBarVerticalGraph, public JKQTPYGraphErrors { Q_OBJECT @@ -241,8 +243,11 @@ class JKQTP_LIB_EXPORT JKQTPBarVerticalErrorGraph: public JKQTPBarVerticalGraph, \ingroup jkqtplotter_barssticks This works much the same as JKQTPBarHorizontalGraph. Here is an example output: + \image html plot_bargraphhorplot.png + + \see \ref JKQTPlotterBarcharts, jkqtpstatAddVHistogram1D(), jkqtpstatAddVHistogram1DAutoranged() */ class JKQTP_LIB_EXPORT JKQTPBarHorizontalGraph: public JKQTPBarVerticalGraph { Q_OBJECT @@ -279,6 +284,8 @@ class JKQTP_LIB_EXPORT JKQTPBarHorizontalGraph: public JKQTPBarVerticalGraph { * Draw stacked barcharts by connecting several plots by calling \c setStackedParent(belowPlot) for each plot * \image html JKQTPBarHorizontalGraphStacked.png * + * + * \see JKQTPBarHorizontalGraph, \ref JKQTPlotterStackedBarChart */ class JKQTP_LIB_EXPORT JKQTPBarHorizontalStackableGraph: public JKQTPBarHorizontalGraph { Q_OBJECT @@ -318,6 +325,8 @@ class JKQTP_LIB_EXPORT JKQTPBarHorizontalStackableGraph: public JKQTPBarHorizont * This works much the same as JKQTPBarHorizontalGraph. Here is an example output: * \image html plot_bargraphhorploterr.png * + * \see jkqtpstatAddXErrorBarGraph(), JKQTPBarHorizontalGraph, \ref JKQTPlotterBarcharts + * */ class JKQTP_LIB_EXPORT JKQTPBarHorizontalErrorGraph: public JKQTPBarHorizontalGraph, public JKQTPXGraphErrors { Q_OBJECT diff --git a/lib/jkqtplotter/jkqtpgraphsboxplot.h b/lib/jkqtplotter/jkqtpgraphsboxplot.h index 0c2e14e052..386575201a 100644 --- a/lib/jkqtplotter/jkqtpgraphsboxplot.h +++ b/lib/jkqtplotter/jkqtpgraphsboxplot.h @@ -95,7 +95,7 @@ graphOutliers->setSymbolSize(7); \endcode - \see \ref JKQTPlotterBoxplotsGraphs + \see \ref JKQTPlotterBoxplotsGraphs, jkqtpstatVAddBoxplots(),\ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat, \ref JKQTPlotterBasicJKQTPDatastoreStatistics, \ref JKQTPlotterBoxplotStyling */ class JKQTP_LIB_EXPORT JKQTPBoxplotVerticalGraph: public JKQTPGraph, public JKQTPGraphBoxplotStyleMixin { @@ -252,7 +252,7 @@ class JKQTP_LIB_EXPORT JKQTPBoxplotVerticalGraph: public JKQTPGraph, public JKQT \note See the documentation of JKQTPBoxplotVerticalGraph for details on the properties of this class! - \see JKQTPBoxplotVerticalGraph \ref JKQTPlotterBoxplotsGraphs + \see JKQTPBoxplotVerticalGraph \ref JKQTPlotterBoxplotsGraphs, jkqtpstatHAddBoxplots(), \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat, \ref JKQTPlotterBasicJKQTPDatastoreStatistics, \ref JKQTPlotterBoxplotStyling */ class JKQTP_LIB_EXPORT JKQTPBoxplotHorizontalGraph: public JKQTPBoxplotVerticalGraph { @@ -306,6 +306,8 @@ class JKQTP_LIB_EXPORT JKQTPBoxplotHorizontalGraph: public JKQTPBoxplotVerticalG \image html test_styledboxplot.png + \see jkqtpstatVAddBoxplot(), \ref JKQTPlotterBasicJKQTPDatastoreStatistics, \ref JKQTPlotterBoxplotsGraphs, \ref JKQTPlotterBoxplotStyling, jkqtpstatAddVBoxplotAndOutliers() + */ class JKQTP_LIB_EXPORT JKQTPBoxplotVerticalElement: public JKQTPPlotObject, public JKQTPGraphBoxplotStyleMixin { Q_OBJECT @@ -428,7 +430,8 @@ class JKQTP_LIB_EXPORT JKQTPBoxplotVerticalElement: public JKQTPPlotObject, publ \note See JKQTPBoxplotVerticalElement for a detailed documentation - \see JKQTPBoxplotVerticalElement + \see JKQTPBoxplotVerticalElement, jkqtpstatHAddBoxplot(), \ref JKQTPlotterBasicJKQTPDatastoreStatistics, \ref JKQTPlotterBoxplotsGraphs, \ref JKQTPlotterBoxplotStyling, jkqtpstatAddHBoxplotAndOutliers() + */ class JKQTP_LIB_EXPORT JKQTPBoxplotHorizontalElement: public JKQTPBoxplotVerticalElement { Q_OBJECT diff --git a/lib/jkqtplotter/jkqtpgraphscontour.h b/lib/jkqtplotter/jkqtpgraphscontour.h index 9a4432a283..f415cfdc3c 100644 --- a/lib/jkqtplotter/jkqtpgraphscontour.h +++ b/lib/jkqtplotter/jkqtpgraphscontour.h @@ -247,6 +247,8 @@ class JKQTP_LIB_EXPORT JKQTPContourPlot: public JKQTPMathImage, public JKQTPGrap * \ingroup jkqtplotter_imagelots_contour * * \copydetails JKQTPContourPlot + * + * \see jkqtpstatAddKDE2DContour(), jkqtpstatAddHistogram2DContour(), \ref JKQTPlotterContourPlot, \ref JKQTPlotterBasicJKQTPDatastoreStatistics2D */ class JKQTP_LIB_EXPORT JKQTPColumnContourPlot: public JKQTPContourPlot { Q_OBJECT diff --git a/lib/jkqtplotter/jkqtpgraphsevaluatedfunction.h b/lib/jkqtplotter/jkqtpgraphsevaluatedfunction.h index 4a35becef0..beb07a4129 100644 --- a/lib/jkqtplotter/jkqtpgraphsevaluatedfunction.h +++ b/lib/jkqtplotter/jkqtpgraphsevaluatedfunction.h @@ -65,6 +65,8 @@ typedef std::function jkqtpSimplePlotFunctionType; the following image \image html plot_functionplots.png + + \see \ref JKQTPlotterFunctionPlots, jkqtpstatAddPolyFit(), jkqtpstatAddWeightedRegression(), jkqtpstatAddRobustIRLSRegression(), jkqtpstatAddRegression(), jkqtpstatAddLinearWeightedRegression(), jkqtpstatAddRobustIRLSLinearRegression(), jkqtpstatAddLinearRegression() */ class JKQTP_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPGraph, public JKQTPGraphLineStyleMixin, public JKQTPGraphFillStyleMixin { Q_OBJECT @@ -392,6 +394,7 @@ class JKQTP_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPGraph, public JKQTPG /*! \brief This implements line plots where the data is taken from a user supplied function \f$ x=f(y) \f$ \ingroup jkqtplotter_functiongraphs + \see \ref JKQTPlotterFunctionPlots */ class JKQTP_LIB_EXPORT JKQTPYFunctionLineGraph: public JKQTPXFunctionLineGraph { Q_OBJECT diff --git a/lib/jkqtplotter/jkqtpgraphsfilledcurve.h b/lib/jkqtplotter/jkqtpgraphsfilledcurve.h index 95b4e71346..c43b3dbbb1 100644 --- a/lib/jkqtplotter/jkqtpgraphsfilledcurve.h +++ b/lib/jkqtplotter/jkqtpgraphsfilledcurve.h @@ -54,7 +54,7 @@ class JKQTP_LIB_EXPORT JKQTPFilledCurveXGraph: public JKQTPSpecialLineHorizontal \image html plot_filledcurvexerrorplots.png - \see \ref JKQTPlotterFilledGraphs + \see \ref JKQTPlotterFilledGraphs, jkqtpstatAddXErrorFilledCurveGraph() */ class JKQTP_LIB_EXPORT JKQTPFilledCurveXErrorGraph: public JKQTPFilledCurveXGraph, public JKQTPYGraphErrors { Q_OBJECT @@ -103,7 +103,7 @@ class JKQTP_LIB_EXPORT JKQTPFilledCurveYGraph: public JKQTPSpecialLineVerticalGr \image html plot_filledcurveyerrorplots.png - \see \ref JKQTPlotterFilledGraphs + \see \ref JKQTPlotterFilledGraphs, jkqtpstatAddYErrorFilledCurveGraph() */ class JKQTP_LIB_EXPORT JKQTPFilledCurveYErrorGraph: public JKQTPFilledCurveYGraph, public JKQTPXGraphErrors { Q_OBJECT diff --git a/lib/jkqtplotter/jkqtpgraphsimage.h b/lib/jkqtplotter/jkqtpgraphsimage.h index 05bf86ab0d..57d8a5655e 100644 --- a/lib/jkqtplotter/jkqtpgraphsimage.h +++ b/lib/jkqtplotter/jkqtpgraphsimage.h @@ -334,6 +334,8 @@ class JKQTP_LIB_EXPORT JKQTPMathImageBase: public JKQTPImageBase { \ingroup jkqtplotter_imagelots_elements \image html jkqtplotter_simpletest_rgbimageplot_qt.png + + \see \ref JKQTPlotterImagePlotQImageRGB */ class JKQTP_LIB_EXPORT JKQTPImage: public JKQTPImageBase { Q_OBJECT @@ -467,6 +469,8 @@ class JKQTP_LIB_EXPORT JKQTPImage: public JKQTPImageBase { \image html jkqtplotter_simpletest_imageplot.png \image html jkqtplotter_simpletest_imageplot_modifier.png \image html jkqtplotter_simpletest_imageplot__smallscaletransparent.png + + \see \ref JKQTPlotterImagePlotNoDatastore */ class JKQTP_LIB_EXPORT JKQTPMathImage: public JKQTPMathImageBase { Q_OBJECT @@ -994,6 +998,7 @@ int JKQTPMathImage::getModifierSampleSize() const { \image html jkqtplotter_simpletest_imageplot_modifier.png \image html jkqtplotter_simpletest_imageplot__smallscaletransparent.png + \see jkqtpstatAddKDE2DImage(), jkqtpstatAddHistogram2DImage(), \ref JKQTPlotterImagePlot, \ref JKQTPlotterImagePlotModifier, \ref JKQTPlotterImagePlotOpenCV */ class JKQTP_LIB_EXPORT JKQTPColumnMathImage: public JKQTPMathImage { Q_OBJECT diff --git a/lib/jkqtplotter/jkqtpgraphsimpulses.h b/lib/jkqtplotter/jkqtpgraphsimpulses.h index 1016a9798a..d9861f069c 100644 --- a/lib/jkqtplotter/jkqtpgraphsimpulses.h +++ b/lib/jkqtplotter/jkqtpgraphsimpulses.h @@ -31,6 +31,8 @@ \ingroup jkqtplotter_barssticks \image html plot_impulsesxplots.png + + \see JKQTPImpulsesVerticalGraph, \ref JKQTPlotterImpulsePlots */ class JKQTP_LIB_EXPORT JKQTPImpulsesHorizontalGraph: public JKQTPXYGraph, public JKQTPGraphLineStyleMixin, public JKQTPGraphSymbolStyleMixin{ Q_OBJECT @@ -80,6 +82,8 @@ class JKQTP_LIB_EXPORT JKQTPImpulsesHorizontalGraph: public JKQTPXYGraph, public \ingroup jkqtplotter_barssticks \image html plot_impulsesxerrorsplots.png + + \see jkqtpstatAddXErrorImpulsesGraph(), JKQTPImpulsesHorizontalGraph, \ref JKQTPlotterImpulsePlots */ class JKQTP_LIB_EXPORT JKQTPImpulsesHorizontalErrorGraph: public JKQTPImpulsesHorizontalGraph, public JKQTPXGraphErrors { Q_OBJECT @@ -103,6 +107,8 @@ class JKQTP_LIB_EXPORT JKQTPImpulsesHorizontalErrorGraph: public JKQTPImpulsesHo \ingroup jkqtplotter_barssticks \image html plot_impulsesyplots.png + + \see \ref JKQTPlotterImpulsePlots */ class JKQTP_LIB_EXPORT JKQTPImpulsesVerticalGraph: public JKQTPImpulsesHorizontalGraph { Q_OBJECT @@ -122,6 +128,8 @@ class JKQTP_LIB_EXPORT JKQTPImpulsesVerticalGraph: public JKQTPImpulsesHorizonta \ingroup jkqtplotter_barssticks \image html plot_impulsesyerrorsplots.png + + \see JKQTPImpulsesVerticalGraph, jkqtpstatAddYErrorImpulsesGraph(), \ref JKQTPlotterImpulsePlots */ class JKQTP_LIB_EXPORT JKQTPImpulsesVerticalErrorGraph: public JKQTPImpulsesVerticalGraph, public JKQTPYGraphErrors { Q_OBJECT diff --git a/lib/jkqtplotter/jkqtpgraphsparsedfunction.h b/lib/jkqtplotter/jkqtpgraphsparsedfunction.h index c7409b98c6..4993087eea 100644 --- a/lib/jkqtplotter/jkqtpgraphsparsedfunction.h +++ b/lib/jkqtplotter/jkqtpgraphsparsedfunction.h @@ -42,6 +42,8 @@ class JKQTPlotter; Parameters may also be given from a data column. Then first the params from the column and the the parameters from the vector are numbered. Use the variable \c x in an equation to refer to the free parameter of the curve. + + \see \ref JKQTPlotterParsedFunctionPlot, JKQTPMathParser */ class JKQTP_LIB_EXPORT JKQTPXParsedFunctionLineGraph: public JKQTPXFunctionLineGraph { Q_OBJECT @@ -108,6 +110,9 @@ class JKQTP_LIB_EXPORT JKQTPXParsedFunctionLineGraph: public JKQTPXFunctionLineG Parameters may also be given from a data column. Then first the params from the column and the the parameters from the vector are numbered. Use the variable \c y in an equation to refer to the free parameter of the curve (\c is also understood for convenience). + + \see \ref JKQTPlotterParsedFunctionPlot, JKQTPMathParser + */ class JKQTP_LIB_EXPORT JKQTPYParsedFunctionLineGraph: public JKQTPYFunctionLineGraph { Q_OBJECT diff --git a/lib/jkqtplotter/jkqtpgraphspeakstream.h b/lib/jkqtplotter/jkqtpgraphspeakstream.h index c9a2c58329..c3bcf27252 100644 --- a/lib/jkqtplotter/jkqtpgraphspeakstream.h +++ b/lib/jkqtplotter/jkqtpgraphspeakstream.h @@ -42,6 +42,8 @@ class JKQTPDatastore; \image html JKQTPPeakStreamGraphY.png "yPeaks=true" \image html JKQTPPeakStreamGraphX.png "yPeaks=false" + + \see \ref JKQTPlotterBasicJKQTPDatastoreStatistics */ class JKQTP_LIB_EXPORT JKQTPPeakStreamGraph: public JKQTPSingleColumnGraph, public JKQTPGraphLineStyleMixin { Q_OBJECT diff --git a/lib/jkqtplotter/jkqtpgraphsscatter.h b/lib/jkqtplotter/jkqtpgraphsscatter.h index 626d10a56d..d1193d09b6 100644 --- a/lib/jkqtplotter/jkqtpgraphsscatter.h +++ b/lib/jkqtplotter/jkqtpgraphsscatter.h @@ -50,6 +50,8 @@ class JKQTPDatastore; \ingroup jkqtplotter_linesymbolgraphs_simple \image html plot_lineplots.png + + \see \ref JKQTPlotterAdvancedLineAndFillStyling, \ref JKQTPlotterSimpleTest, \ref JKQTPlotterSymbolsAndStyles, jkqtpstatAddVKDE1D(), jkqtpstatAddVKDE1DAutoranged(), jkqtpstatAddHKDE1D(), jkqtpstatAddHKDE1DAutoranged() */ class JKQTP_LIB_EXPORT JKQTPXYLineGraph: public JKQTPXYGraph, public JKQTPGraphLineStyleMixin, public JKQTPGraphSymbolStyleMixin { Q_OBJECT @@ -109,7 +111,7 @@ class JKQTP_LIB_EXPORT JKQTPXYLineGraph: public JKQTPXYGraph, public JKQTPGraphL \image html JKQTPXYParametrizedScatterGraph_SymbolFunctor.png - \see JKQTPXYParametrizedErrorScatterGraph, \ref JKQTPlotterParamScatter , \ref JKQTPlotterParamScatterImage + \see JKQTPXYParametrizedErrorScatterGraph, \ref JKQTPlotterParamScatter , \ref JKQTPlotterParamScatterImage, \ref JKQTPlotterParametricCurves */ class JKQTP_LIB_EXPORT JKQTPXYParametrizedScatterGraph: public JKQTPXYLineGraph, public JKQTPColorPaletteStyleAndToolsMixin { Q_OBJECT @@ -367,6 +369,8 @@ class JKQTP_LIB_EXPORT JKQTPXYParametrizedScatterGraph: public JKQTPXYLineGraph, \image html plot_errorbarlineplots.png \image html plot_errorlinelineplots.png \image html plot_errorpolygonlineplots.png + + \see jkqtpstatAddXYErrorLineGraph(), jkqtpstatAddXErrorLineGraph(), jkqtpstatAddYErrorLineGraph(), \ref JKQTPlotterErrorBarStyles, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat */ class JKQTP_LIB_EXPORT JKQTPXYLineErrorGraph: public JKQTPXYLineGraph, public JKQTPXYGraphErrors { Q_OBJECT @@ -403,7 +407,7 @@ class JKQTP_LIB_EXPORT JKQTPXYLineErrorGraph: public JKQTPXYLineGraph, public JK \image html screen_parmetrizedplots_datatable.png - \see JKQTPXYParametrizedScatterGraph, \ref JKQTPlotterParamScatter + \see JKQTPXYParametrizedScatterGraph, \ref JKQTPlotterParamScatter, jkqtpstatAddXErrorParametrizedScatterGraph(), jkqtpstatAddYErrorParametrizedScatterGraph() */ class JKQTP_LIB_EXPORT JKQTPXYParametrizedErrorScatterGraph: public JKQTPXYParametrizedScatterGraph, public JKQTPXYGraphErrors { Q_OBJECT diff --git a/lib/jkqtplotter/jkqtpgraphsstatisticsadaptors.h b/lib/jkqtplotter/jkqtpgraphsstatisticsadaptors.h index 0a5035afb2..04d1ff0536 100644 --- a/lib/jkqtplotter/jkqtpgraphsstatisticsadaptors.h +++ b/lib/jkqtplotter/jkqtpgraphsstatisticsadaptors.h @@ -30,6 +30,8 @@ #include "jkqtplotter/jkqtpgraphsevaluatedfunction.h" #include "jkqtplotter/jkqtpgraphsimage.h" #include "jkqtplotter/jkqtpgraphscontour.h" +#include "jkqtplotter/jkqtpgraphsimpulses.h" +#include "jkqtplotter/jkqtpgraphsfilledcurve.h" #ifndef JKQTPGRAPHSSTATISTICSADAPTORS_H_INCLUDED @@ -1788,4 +1790,735 @@ JKQTP_LIB_EXPORT JKQTPXFunctionLineGraph* jkqtpstatAddPolyFit(JKQTPXYGraph *data + + + + + + + +/*! \brief create a plot with y-direction error bars, calculated from average +/- stddev of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + + \tparam TGraph type of graph that should be added to the plot + \tparam InputCatIt standard iterator type of \a inFirstCat_X and \a inLastCat_X + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_X iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for x-coordinates) + \param inLastCat_X iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for x-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for y-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for y-coordinates) + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the graph showing \f$ c_{\text{out},j} \f$ and average +/- stddev for each group \f$ j \f$ + + + + \see jkqtpstatGroupData(), \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline TGraph* jkqtpstatAddYErrorGraph(JKQTBasePlotter* plotter, InputCatIt inFirstCat_X, InputCatIt inLastCat_X, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped data")) { + std::map > groupeddataBar; + jkqtpstatGroupData(inFirstCat_X, inLastCat_X, inFirstValue_Y, inLastValue_Y, groupeddataBar, groupDefFunc); + + size_t colGroup=plotter->getDatastore()->addColumn(columnBaseName+", group"); + size_t colAverage=plotter->getDatastore()->addColumn(columnBaseName+", average"); + size_t colStdDev=plotter->getDatastore()->addColumn(columnBaseName+", stddev"); + + for (auto it=groupeddataBar.begin(); it!=groupeddataBar.end(); ++it) { + plotter->getDatastore()->appendToColumn(colGroup, it->first); + plotter->getDatastore()->appendToColumn(colAverage, jkqtpstatAverage(it->second.begin(), it->second.end())); + plotter->getDatastore()->appendToColumn(colStdDev, jkqtpstatStdDev(it->second.begin(), it->second.end())); + } + + // 2.4. Finally the calculated groups are drawn + TGraph* graph; + plotter->addGraph(graph=new TGraph(plotter)); + graph->setXColumn(colGroup); + graph->setYColumn(colAverage); + graph->setYErrorColumn(static_cast(colStdDev)); + + return graph; +} + + +/*! \brief create a JKQTPXYLineErrorGraph with y-direction error bars, calculated from average +/- stddev of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputCatIt standard iterator type of \a inFirstCat_X and \a inLastCat_X + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_X iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for x-coordinates) + \param inLastCat_X iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for x-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for y-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for y-coordinates) + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the graph showing \f$ c_{\text{out},j} \f$ and average +/- stddev for each group \f$ j \f$ + + + + \see jkqtpstatGroupData(), jkqtpstatAddYErrorGraph(), JKQTPXYLineErrorGraph, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline JKQTPXYLineErrorGraph* jkqtpstatAddYErrorLineGraph(JKQTBasePlotter* plotter, InputCatIt inFirstCat_X, InputCatIt inLastCat_X, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped data")) { + return jkqtpstatAddYErrorGraph(plotter,inFirstCat_X, inLastCat_X, inFirstValue_Y, inLastValue_Y, groupDefFunc, columnBaseName); +} + + +/*! \brief create a JKQTPBarVerticalErrorGraph with y-direction error bars, calculated from average +/- stddev of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputCatIt standard iterator type of \a inFirstCat_X and \a inLastCat_X + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_X iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for x-coordinates) + \param inLastCat_X iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for x-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for y-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for y-coordinates) + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the graph showing \f$ c_{\text{out},j} \f$ and average +/- stddev for each group \f$ j \f$ + + + + \see jkqtpstatGroupData(), jkqtpstatAddYErrorGraph(), JKQTPBarVerticalErrorGraph, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline JKQTPBarVerticalErrorGraph* jkqtpstatAddYErrorBarGraph(JKQTBasePlotter* plotter, InputCatIt inFirstCat_X, InputCatIt inLastCat_X, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped data")) { + return jkqtpstatAddYErrorGraph(plotter,inFirstCat_X, inLastCat_X, inFirstValue_Y, inLastValue_Y, groupDefFunc, columnBaseName); +} + + +/*! \brief create a JKQTPImpulsesVerticalErrorGraph with y-direction error bars, calculated from average +/- stddev of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputCatIt standard iterator type of \a inFirstCat_X and \a inLastCat_X + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_X iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for x-coordinates) + \param inLastCat_X iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for x-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for y-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for y-coordinates) + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the graph showing \f$ c_{\text{out},j} \f$ and average +/- stddev for each group \f$ j \f$ + + + + \see jkqtpstatGroupData(), jkqtpstatAddYErrorGraph(), JKQTPImpulsesVerticalErrorGraph, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline JKQTPImpulsesVerticalErrorGraph* jkqtpstatAddYErrorImpulsesGraph(JKQTBasePlotter* plotter, InputCatIt inFirstCat_X, InputCatIt inLastCat_X, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped data")) { + return jkqtpstatAddYErrorGraph(plotter,inFirstCat_X, inLastCat_X, inFirstValue_Y, inLastValue_Y, groupDefFunc, columnBaseName); +} + + +/*! \brief create a JKQTPXYParametrizedErrorScatterGraph with y-direction error bars, calculated from average +/- stddev of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputCatIt standard iterator type of \a inFirstCat_X and \a inLastCat_X + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_X iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for x-coordinates) + \param inLastCat_X iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for x-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for y-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for y-coordinates) + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the graph showing \f$ c_{\text{out},j} \f$ and average +/- stddev for each group \f$ j \f$ + + + + \see jkqtpstatGroupData(), jkqtpstatAddYErrorGraph(), JKQTPXYParametrizedErrorScatterGraph, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline JKQTPXYParametrizedErrorScatterGraph* jkqtpstatAddYErrorParametrizedScatterGraph(JKQTBasePlotter* plotter, InputCatIt inFirstCat_X, InputCatIt inLastCat_X, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped data")) { + return jkqtpstatAddYErrorGraph(plotter,inFirstCat_X, inLastCat_X, inFirstValue_Y, inLastValue_Y, groupDefFunc, columnBaseName); +} + + +/*! \brief create a JKQTPFilledCurveYErrorGraph with y-direction error bars, calculated from average +/- stddev of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputCatIt standard iterator type of \a inFirstCat_X and \a inLastCat_X + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_X iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for x-coordinates) + \param inLastCat_X iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for x-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for y-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for y-coordinates) + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the graph showing \f$ c_{\text{out},j} \f$ and average +/- stddev for each group \f$ j \f$ + + + + \see jkqtpstatGroupData(), jkqtpstatAddYErrorGraph(), JKQTPFilledCurveYErrorGraph, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline JKQTPFilledCurveYErrorGraph* jkqtpstatAddYErrorFilledCurveGraph(JKQTBasePlotter* plotter, InputCatIt inFirstCat_X, InputCatIt inLastCat_X, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped data")) { + return jkqtpstatAddYErrorGraph(plotter,inFirstCat_X, inLastCat_X, inFirstValue_Y, inLastValue_Y, groupDefFunc, columnBaseName); +} + + + + + + + +/*! \brief create a plot with x-direction error bars, calculated from average +/- stddev of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + + \tparam TGraph type of graph that should be added to the plot + \tparam InputCatIt standard iterator type of \a inFirstCat_Y and \a inLastCat_Y + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_Y iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for y-coordinates) + \param inLastCat_Y iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for y-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for x-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for x-coordinates) + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the graph showing \f$ c_{\text{out},j} \f$ and average +/- stddev for each group \f$ j \f$ + + + + \see jkqtpstatGroupData(), \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline TGraph* jkqtpstatAddXErrorGraph(JKQTBasePlotter* plotter, InputCatIt inFirstCat_Y, InputCatIt inLastCat_Y, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped data")) { + std::map > groupeddataBar; + jkqtpstatGroupData(inFirstCat_Y, inLastCat_Y, inFirstValue_Y, inLastValue_Y, groupeddataBar, groupDefFunc); + + size_t colGroup=plotter->getDatastore()->addColumn(columnBaseName+", group"); + size_t colAverage=plotter->getDatastore()->addColumn(columnBaseName+", average"); + size_t colStdDev=plotter->getDatastore()->addColumn(columnBaseName+", stddev"); + + for (auto it=groupeddataBar.begin(); it!=groupeddataBar.end(); ++it) { + plotter->getDatastore()->appendToColumn(colGroup, it->first); + plotter->getDatastore()->appendToColumn(colAverage, jkqtpstatAverage(it->second.begin(), it->second.end())); + plotter->getDatastore()->appendToColumn(colStdDev, jkqtpstatStdDev(it->second.begin(), it->second.end())); + } + + // 2.4. Finally the calculated groups are drawn + TGraph* graph; + plotter->addGraph(graph=new TGraph(plotter)); + graph->setXColumn(colAverage); + graph->setYColumn(colGroup); + graph->setXErrorColumn(static_cast(colStdDev)); + + return graph; +} + + +/*! \brief create a JKQTPXYLineErrorGraph with x-direction error bars, calculated from average +/- stddev of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputCatIt standard iterator type of \a inFirstCat_Y and \a inLastCat_Y + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_Y iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for y-coordinates) + \param inLastCat_Y iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for y-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for x-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for x-coordinates) + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the graph showing \f$ c_{\text{out},j} \f$ and average +/- stddev for each group \f$ j \f$ + + + + \see jkqtpstatGroupData(), jkqtpstatAddXErrorGraph(), JKQTPXYLineErrorGraph, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline JKQTPXYLineErrorGraph* jkqtpstatAddXErrorLineGraph(JKQTBasePlotter* plotter, InputCatIt inFirstCat_Y, InputCatIt inLastCat_Y, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped data")) { + return jkqtpstatAddXErrorGraph(plotter,inFirstCat_Y, inLastCat_Y, inFirstValue_Y, inLastValue_Y, groupDefFunc, columnBaseName); +} + + +/*! \brief create a JKQTPBarHorizontalErrorGraph with x-direction error bars, calculated from average +/- stddev of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputCatIt standard iterator type of \a inFirstCat_Y and \a inLastCat_Y + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_Y iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for y-coordinates) + \param inLastCat_Y iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for y-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for x-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for x-coordinates) + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the graph showing \f$ c_{\text{out},j} \f$ and average +/- stddev for each group \f$ j \f$ + + + + \see jkqtpstatGroupData(), jkqtpstatAddXErrorGraph(), JKQTPBarHorizontalErrorGraph, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline JKQTPBarHorizontalErrorGraph* jkqtpstatAddXErrorBarGraph(JKQTBasePlotter* plotter, InputCatIt inFirstCat_Y, InputCatIt inLastCat_Y, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped data")) { + return jkqtpstatAddXErrorGraph(plotter,inFirstCat_Y, inLastCat_Y, inFirstValue_Y, inLastValue_Y, groupDefFunc, columnBaseName); +} + + +/*! \brief create a JKQTPImpulsesHorizontalErrorGraph with x-direction error bars, calculated from average +/- stddev of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputCatIt standard iterator type of \a inFirstCat_Y and \a inLastCat_Y + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_Y iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for y-coordinates) + \param inLastCat_Y iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for y-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for x-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for x-coordinates) + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the graph showing \f$ c_{\text{out},j} \f$ and average +/- stddev for each group \f$ j \f$ + + + + \see jkqtpstatGroupData(), jkqtpstatAddXErrorGraph(), JKQTPImpulsesHorizontalErrorGraph, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline JKQTPImpulsesHorizontalErrorGraph* jkqtpstatAddXErrorImpulsesGraph(JKQTBasePlotter* plotter, InputCatIt inFirstCat_Y, InputCatIt inLastCat_Y, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped data")) { + return jkqtpstatAddXErrorGraph(plotter,inFirstCat_Y, inLastCat_Y, inFirstValue_Y, inLastValue_Y, groupDefFunc, columnBaseName); +} + + +/*! \brief create a JKQTPXYParametrizedErrorScatterGraph with x-direction error bars, calculated from average +/- stddev of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputCatIt standard iterator type of \a inFirstCat_Y and \a inLastCat_Y + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_Y iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for y-coordinates) + \param inLastCat_Y iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for y-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for x-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for x-coordinates) + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the graph showing \f$ c_{\text{out},j} \f$ and average +/- stddev for each group \f$ j \f$ + + + + \see jkqtpstatGroupData(), jkqtpstatAddXErrorGraph(), JKQTPXYParametrizedErrorScatterGraph, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline JKQTPXYParametrizedErrorScatterGraph* jkqtpstatAddXErrorParametrizedScatterGraph(JKQTBasePlotter* plotter, InputCatIt inFirstCat_Y, InputCatIt inLastCat_Y, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped data")) { + return jkqtpstatAddXErrorGraph(plotter,inFirstCat_Y, inLastCat_Y, inFirstValue_Y, inLastValue_Y, groupDefFunc, columnBaseName); +} + + +/*! \brief create a JKQTPFilledCurveXErrorGraph with x-direction error bars, calculated from average +/- stddev of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputCatIt standard iterator type of \a inFirstCat_Y and \a inLastCat_Y + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_Y iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for y-coordinates) + \param inLastCat_Y iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for y-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for x-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for x-coordinates) + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the graph showing \f$ c_{\text{out},j} \f$ and average +/- stddev for each group \f$ j \f$ + + + + \see jkqtpstatGroupData(), jkqtpstatAddXErrorGraph(), JKQTPFilledCurveXErrorGraph, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline JKQTPFilledCurveXErrorGraph* jkqtpstatAddXErrorFilledCurveGraph(JKQTBasePlotter* plotter, InputCatIt inFirstCat_Y, InputCatIt inLastCat_Y, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped data")) { + return jkqtpstatAddXErrorGraph(plotter,inFirstCat_Y, inLastCat_Y, inFirstValue_Y, inLastValue_Y, groupDefFunc, columnBaseName); +} + + + + + + + + +/*! \brief create a plot with x- and y-direction error bars, calculated from directional average +/- stddev of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + + \tparam TGraph type of graph that should be added to the plot + \tparam InputCatIt standard iterator type of \a inFirstCat_X and \a inLastCat_X + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_X iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for x-coordinates) + \param inLastCat_X iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for x-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for y-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for y-coordinates) + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the graph showing \f$ c_{\text{out},j} \f$ and average +/- stddev for each group \f$ j \f$ + + + + \see jkqtpstatGroupData(), \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline TGraph* jkqtpstatAddXYErrorGraph(JKQTBasePlotter* plotter, InputCatIt inFirstCat_X, InputCatIt inLastCat_X, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped data")) { + std::map, std::vector > > groupeddataBar; + jkqtpstatGroupData(inFirstCat_X, inLastCat_X, inFirstValue_Y, inLastValue_Y, groupeddataBar, groupDefFunc); + + size_t colGroup=plotter->getDatastore()->addColumn(columnBaseName+", group"); + size_t colAverageX=plotter->getDatastore()->addColumn(columnBaseName+", category-average"); + size_t colStdDevX=plotter->getDatastore()->addColumn(columnBaseName+", category-stddev"); + size_t colAverageY=plotter->getDatastore()->addColumn(columnBaseName+", value-average"); + size_t colStdDevY=plotter->getDatastore()->addColumn(columnBaseName+", value-stddev"); + + for (auto it=groupeddataBar.begin(); it!=groupeddataBar.end(); ++it) { + plotter->getDatastore()->appendToColumn(colGroup, it->first); + plotter->getDatastore()->appendToColumn(colAverageX, jkqtpstatAverage(it->second.first.begin(), it->second.first.end())); + plotter->getDatastore()->appendToColumn(colStdDevX, jkqtpstatStdDev(it->second.first.begin(), it->second.first.end())); + plotter->getDatastore()->appendToColumn(colAverageY, jkqtpstatAverage(it->second.second.begin(), it->second.second.end())); + plotter->getDatastore()->appendToColumn(colStdDevY, jkqtpstatStdDev(it->second.second.begin(), it->second.second.end())); + } + + // 2.4. Finally the calculated groups are drawn + TGraph* graph; + plotter->addGraph(graph=new TGraph(plotter)); + graph->setXColumn(colAverageX); + graph->setYColumn(colAverageY); + graph->setXErrorColumn(static_cast(colStdDevX)); + graph->setYErrorColumn(static_cast(colStdDevY)); + + return graph; +} + + +/*! \brief create a JKQTPXYLineErrorGraph with y-direction error bars, calculated from average +/- stddev of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputCatIt standard iterator type of \a inFirstCat_X and \a inLastCat_X + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_X iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for x-coordinates) + \param inLastCat_X iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for x-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for y-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for y-coordinates) + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the graph showing \f$ c_{\text{out},j} \f$ and average +/- stddev for each group \f$ j \f$ + + + + \see jkqtpstatGroupData(), jkqtpstatAddXYErrorGraph(), JKQTPXYLineErrorGraph, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline JKQTPXYLineErrorGraph* jkqtpstatAddXYErrorLineGraph(JKQTBasePlotter* plotter, InputCatIt inFirstCat_X, InputCatIt inLastCat_X, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped data")) { + return jkqtpstatAddXYErrorGraph(plotter,inFirstCat_X, inLastCat_X, inFirstValue_Y, inLastValue_Y, groupDefFunc, columnBaseName); +} + + + +/*! \brief create a JKQTPXYParametrizedErrorScatterGraph with y-direction error bars, calculated from average +/- stddev of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputCatIt standard iterator type of \a inFirstCat_X and \a inLastCat_X + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_X iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for x-coordinates) + \param inLastCat_X iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for x-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for y-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for y-coordinates) + \param groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the graph showing \f$ c_{\text{out},j} \f$ and average +/- stddev for each group \f$ j \f$ + + + + \see jkqtpstatGroupData(), jkqtpstatAddXYErrorGraph(), JKQTPXYParametrizedErrorScatterGraph, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline JKQTPXYParametrizedErrorScatterGraph* jkqtpstatAddXYErrorParametrizedScatterGraph(JKQTBasePlotter* plotter, InputCatIt inFirstCat_X, InputCatIt inLastCat_X, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped data")) { + return jkqtpstatAddXYErrorGraph(plotter,inFirstCat_X, inLastCat_X, inFirstValue_Y, inLastValue_Y, groupDefFunc, columnBaseName); +} + + + + + +/*! \brief create horizontal boxplots of type \­a TGraph, from the 5-value-summary of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + \internal + + \tparam TGraph type of graph that should be added to the plot, has to offer the same interface as JKQTPBoxplotVerticalGraph or JKQTPBoxplotHorizontalGraph + \tparam InputCatIt standard iterator type of \a inFirstCat_Y and \a inLastCat_Y + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_Y iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for y-coordinates) + \param inLastCat_Y iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for y-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for x-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for x-coordinates) + \param quantile1Spec specifies which quantile to calculate for \a qantile1 (range: 0..1) + \param quantile2Spec specifies which quantile to calculate for \a qantile2 (range: 0..1) + \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 groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the boxplot graph + + + + \see jkqtpstatGroupData(), \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline TGraph* jkqtpstatAddBoxplots(JKQTBasePlotter* plotter, InputCatIt inFirstCat_Y, InputCatIt inLastCat_Y, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, double quantile1Spec=0.25, double quantile2Spec=0.75, double minimumQuantile=0, double maximumQuantile=1.0, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped boxplot data")) { + std::map > groupeddataBar; + jkqtpstatGroupData(inFirstCat_Y, inLastCat_Y, inFirstValue_Y, inLastValue_Y, groupeddataBar, groupDefFunc); + + size_t colGroup=plotter->getDatastore()->addColumn(columnBaseName+", group"); + size_t colMin=plotter->getDatastore()->addColumn(columnBaseName+", minimum"); + size_t colQ25=plotter->getDatastore()->addColumn(columnBaseName+", quartile25"); + size_t colMedian=plotter->getDatastore()->addColumn(columnBaseName+", median"); + size_t colIQRSig=plotter->getDatastore()->addColumn(columnBaseName+", MedianSignificance"); + size_t colAverage=plotter->getDatastore()->addColumn(columnBaseName+", average"); + size_t colQ75=plotter->getDatastore()->addColumn(columnBaseName+", quartile75"); + size_t colMax=plotter->getDatastore()->addColumn(columnBaseName+", maximum"); + + for (auto it=groupeddataBar.begin(); it!=groupeddataBar.end(); ++it) { + + auto stat5=jkqtpstat5NumberStatistics(it->second.begin(), it->second.end(), quantile1Spec, quantile2Spec, minimumQuantile, maximumQuantile); + + plotter->getDatastore()->appendToColumn(colGroup, it->first); + plotter->getDatastore()->appendToColumn(colAverage, jkqtpstatAverage(it->second.begin(), it->second.end())); + plotter->getDatastore()->appendToColumn(colMin, stat5.minimum); + plotter->getDatastore()->appendToColumn(colQ25, stat5.quantile1); + plotter->getDatastore()->appendToColumn(colMedian, stat5.median); + plotter->getDatastore()->appendToColumn(colQ75, stat5.quantile2); + plotter->getDatastore()->appendToColumn(colMax, stat5.maximum); + plotter->getDatastore()->appendToColumn(colIQRSig, stat5.IQRSignificanceEstimate()); + } + + // 2.4. Finally the calculated groups are drawn + TGraph* graph; + plotter->addGraph(graph=new TGraph(plotter)); + graph->setPositionColumn(colGroup); + graph->setMinColumn(colMin); + graph->setMaxColumn(colMax); + graph->setMedianColumn(colMedian); + graph->setMeanColumn(colAverage); + graph->setPercentile25Column(colQ25); + graph->setPercentile75Column(colQ75); + graph->setMedianConfidenceColumn(colIQRSig); + + return graph; +} + +/*! \brief create vertical boxplots of type \­a JKQTPBoxplotVerticalGraph, from the 5-value-summary of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + \internal + + \tparam InputCatIt standard iterator type of \a inFirstCat_Y and \a inLastCat_Y + \tparam InputValueIt standard iterator type of \a inFirstValue_X and \a inLastValue_X + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_Y iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for y-coordinates) + \param inLastCat_Y iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for y-coordinates) + \param inFirstValue_X iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for x-coordinates) + \param inLastValue_X iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for x-coordinates) + \param quantile1Spec specifies which quantile to calculate for \a qantile1 (range: 0..1) + \param quantile2Spec specifies which quantile to calculate for \a qantile2 (range: 0..1) + \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 groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the boxplot graph + + + + \see jkqtpstatGroupData(), \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline JKQTPBoxplotVerticalGraph* jkqtpstatVAddBoxplots(JKQTBasePlotter* plotter, InputCatIt inFirstCat_Y, InputCatIt inLastCat_Y, InputValueIt inFirstValue_X, InputValueIt inLastValue_X, double quantile1Spec=0.25, double quantile2Spec=0.75, double minimumQuantile=0, double maximumQuantile=1.0, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped boxplot data")) { + + return jkqtpstatAddBoxplots(plotter, inFirstCat_Y, inLastCat_Y, inFirstValue_X, inLastValue_X, quantile1Spec, quantile2Spec, minimumQuantile, maximumQuantile, groupDefFunc, columnBaseName); +} + +/*! \brief create horizontal boxplots of type \­a JKQTPBoxplotHorizontalGraph, from the 5-value-summary of groups in the input data + \ingroup jkqtptools_math_statistics_adaptors + \internal + + \tparam InputCatIt standard iterator type of \a inFirstCat_X and \a inLastCat_X + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_X iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for y-coordinates) + \param inLastCat_X iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for y-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for x-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for x-coordinates) + \param quantile1Spec specifies which quantile to calculate for \a qantile1 (range: 0..1) + \param quantile2Spec specifies which quantile to calculate for \a qantile2 (range: 0..1) + \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 groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the boxplot graph + + + + \see jkqtpstatGroupData(), \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline JKQTPBoxplotHorizontalGraph* jkqtpstatVAddBoxplots(JKQTBasePlotter* plotter, InputCatIt inFirstCat_X, InputCatIt inLastCat_X, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, double quantile1Spec=0.25, double quantile2Spec=0.75, double minimumQuantile=0, double maximumQuantile=1.0, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped boxplot data")) { + + return jkqtpstatAddBoxplots(plotter, inFirstCat_X, inLastCat_X, inFirstValue_Y, inLastValue_Y, quantile1Spec, quantile2Spec, minimumQuantile, maximumQuantile, groupDefFunc, columnBaseName); +} + +/*! \brief create vertical boxplots of type \­a JKQTPBoxplotVerticalGraph, from the 5-value-summary of groups in the input data, also adds a graph showing the outliers + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputCatIt standard iterator type of \a inFirstCat_X and \a inLastCat_X + \tparam InputValueIt standard iterator type of \a inFirstValue_Y and \a inLastValue_Y + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_X iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for y-coordinates) + \param inLastCat_X iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for y-coordinates) + \param inFirstValue_Y iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for x-coordinates) + \param inLastValue_Y iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for x-coordinates) + \param quantile1Spec specifies which quantile to calculate for \a qantile1 (range: 0..1) + \param quantile2Spec specifies which quantile to calculate for \a qantile2 (range: 0..1) + \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 groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the boxplot graph (return.first) and the outliers graph (return.second) + + + + \see jkqtpstatGroupData(), \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline std::pair jkqtpstatAddVBoxplotsAndOutliers(JKQTBasePlotter* plotter, InputCatIt inFirstCat_X, InputCatIt inLastCat_X, InputValueIt inFirstValue_Y, InputValueIt inLastValue_Y, double quantile1Spec=0.25, double quantile2Spec=0.75, double minimumQuantile=0.03, double maximumQuantile=0.97, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped boxplot data")) { + std::map > groupeddataBar; + jkqtpstatGroupData(inFirstCat_X, inLastCat_X, inFirstValue_Y, inLastValue_Y, groupeddataBar, groupDefFunc); + + size_t colGroup=plotter->getDatastore()->addColumn(columnBaseName+", group"); + size_t colMin=plotter->getDatastore()->addColumn(columnBaseName+", minimum"); + size_t colQ25=plotter->getDatastore()->addColumn(columnBaseName+", quartile25"); + size_t colMedian=plotter->getDatastore()->addColumn(columnBaseName+", median"); + size_t colIQRSig=plotter->getDatastore()->addColumn(columnBaseName+", MedianSignificance"); + size_t colAverage=plotter->getDatastore()->addColumn(columnBaseName+", average"); + size_t colQ75=plotter->getDatastore()->addColumn(columnBaseName+", quartile75"); + size_t colMax=plotter->getDatastore()->addColumn(columnBaseName+", maximum"); + size_t colOutlierG=plotter->getDatastore()->addColumn(columnBaseName+", outlier-group"); + size_t colOutlierV=plotter->getDatastore()->addColumn(columnBaseName+", outlier-value"); + + for (auto it=groupeddataBar.begin(); it!=groupeddataBar.end(); ++it) { + + auto stat5=jkqtpstat5NumberStatistics(it->second.begin(), it->second.end(), quantile1Spec, quantile2Spec, minimumQuantile, maximumQuantile); + + plotter->getDatastore()->appendToColumn(colGroup, it->first); + plotter->getDatastore()->appendToColumn(colAverage, jkqtpstatAverage(it->second.begin(), it->second.end())); + plotter->getDatastore()->appendToColumn(colMin, stat5.minimum); + plotter->getDatastore()->appendToColumn(colQ25, stat5.quantile1); + plotter->getDatastore()->appendToColumn(colMedian, stat5.median); + plotter->getDatastore()->appendToColumn(colQ75, stat5.quantile2); + plotter->getDatastore()->appendToColumn(colMax, stat5.maximum); + plotter->getDatastore()->appendToColumn(colIQRSig, stat5.IQRSignificanceEstimate()); + std::fill_n(plotter->getDatastore()->backInserter(colOutlierG), stat5.outliers.size(), jkqtp_todouble(it->first)); + plotter->getDatastore()->appendToColumn(colOutlierV, stat5.outliers.begin(), stat5.outliers.end()); + } + + JKQTPBoxplotVerticalGraph* graph; + plotter->addGraph(graph=new JKQTPBoxplotVerticalGraph(plotter)); + graph->setPositionColumn(colGroup); + graph->setMinColumn(colMin); + graph->setMaxColumn(colMax); + graph->setMedianColumn(colMedian); + graph->setMeanColumn(colAverage); + graph->setPercentile25Column(colQ25); + graph->setPercentile75Column(colQ75); + graph->setMedianConfidenceColumn(colIQRSig); + + JKQTPXYLineGraph* graphOL; + plotter->addGraph(graphOL=new JKQTPXYLineGraph(plotter)); + graphOL->setXColumn(colOutlierG); + graphOL->setYColumn(colOutlierV); + graphOL->setDrawLine(false); + graphOL->setSymbolSize(graphOL->getSymbolSize()/2.0); + graphOL->setColor(graph->getLineColor()); + return std::pair(graph, graphOL); +} + + +/*! \brief create vertical boxplots of type \­a JKQTPBoxplotHorizontalGraph, from the 5-value-summary of groups in the input data, also adds a graph showing the outliers + \ingroup jkqtptools_math_statistics_adaptors + + \tparam InputCatIt standard iterator type of \a inFirstCat_Y and \a inLastCat_Y + \tparam InputValueIt standard iterator type of \a inFirstValue_X and \a inLastValue_X + \param plotter the plotter to which to add the resulting graph + \param inFirstCat_Y iterator pointing to the first item in the category dataset to use \f$ c_1 \f$ (used for y-coordinates) + \param inLastCat_Y iterator pointing behind the last item in the category dataset to use \f$ c_N \f$ (used for y-coordinates) + \param inFirstValue_X iterator pointing to the first item in the category dataset to use \f$ v_1 \f$ (used for x-coordinates) + \param inLastValue_X iterator pointing behind the last item in the category dataset to use \f$ v_N \f$ (used for x-coordinates) + \param quantile1Spec specifies which quantile to calculate for \a qantile1 (range: 0..1) + \param quantile2Spec specifies which quantile to calculate for \a qantile2 (range: 0..1) + \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 groupDefFunc assigns a group \f$ c_{\text{out},j} \f$ to each category value \f$ c_i \f$ . + \param columnBaseName string component used to build the names of the columns generated by this function + \return the boxplot graph (return.first) and the outliers graph (return.second) + + + + \see jkqtpstatGroupData(), \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat +*/ +template +inline std::pair jkqtpstatAddHBoxplotsAndOutliers(JKQTBasePlotter* plotter, InputCatIt inFirstCat_Y, InputCatIt inLastCat_Y, InputValueIt inFirstValue_X, InputValueIt inLastValue_X, double quantile1Spec=0.25, double quantile2Spec=0.75, double minimumQuantile=0.03, double maximumQuantile=0.97, JKQTPStatGroupDefinitionFunctor1D groupDefFunc=&jkqtpstatGroupingIdentity1D, const QString& columnBaseName=QString("grouped boxplot data")) { + std::map > groupeddataBar; + jkqtpstatGroupData(inFirstCat_Y, inLastCat_Y, inFirstValue_X, inLastValue_X, groupeddataBar, groupDefFunc); + + size_t colGroup=plotter->getDatastore()->addColumn(columnBaseName+", group"); + size_t colMin=plotter->getDatastore()->addColumn(columnBaseName+", minimum"); + size_t colQ25=plotter->getDatastore()->addColumn(columnBaseName+", quartile25"); + size_t colMedian=plotter->getDatastore()->addColumn(columnBaseName+", median"); + size_t colIQRSig=plotter->getDatastore()->addColumn(columnBaseName+", MedianSignificance"); + size_t colAverage=plotter->getDatastore()->addColumn(columnBaseName+", average"); + size_t colQ75=plotter->getDatastore()->addColumn(columnBaseName+", quartile75"); + size_t colMax=plotter->getDatastore()->addColumn(columnBaseName+", maximum"); + size_t colOutlierG=plotter->getDatastore()->addColumn(columnBaseName+", outlier-group"); + size_t colOutlierV=plotter->getDatastore()->addColumn(columnBaseName+", outlier-value"); + + for (auto it=groupeddataBar.begin(); it!=groupeddataBar.end(); ++it) { + + auto stat5=jkqtpstat5NumberStatistics(it->second.begin(), it->second.end(), quantile1Spec, quantile2Spec, minimumQuantile, maximumQuantile); + + plotter->getDatastore()->appendToColumn(colGroup, it->first); + plotter->getDatastore()->appendToColumn(colAverage, jkqtpstatAverage(it->second.begin(), it->second.end())); + plotter->getDatastore()->appendToColumn(colMin, stat5.minimum); + plotter->getDatastore()->appendToColumn(colQ25, stat5.quantile1); + plotter->getDatastore()->appendToColumn(colMedian, stat5.median); + plotter->getDatastore()->appendToColumn(colQ75, stat5.quantile2); + plotter->getDatastore()->appendToColumn(colMax, stat5.maximum); + plotter->getDatastore()->appendToColumn(colIQRSig, stat5.IQRSignificanceEstimate()); + std::fill_n(plotter->getDatastore()->backInserter(colOutlierG), stat5.outliers.size(), jkqtp_todouble(it->first)); + plotter->getDatastore()->appendToColumn(colOutlierV, stat5.outliers.begin(), stat5.outliers.end()); + } + + JKQTPBoxplotHorizontalGraph* graph; + plotter->addGraph(graph=new JKQTPBoxplotHorizontalGraph(plotter)); + graph->setPositionColumn(colGroup); + graph->setMinColumn(colMin); + graph->setMaxColumn(colMax); + graph->setMedianColumn(colMedian); + graph->setMeanColumn(colAverage); + graph->setPercentile25Column(colQ25); + graph->setPercentile75Column(colQ75); + graph->setMedianConfidenceColumn(colIQRSig); + + JKQTPXYLineGraph* graphOL; + plotter->addGraph(graphOL=new JKQTPXYLineGraph(plotter)); + graphOL->setYColumn(colOutlierG); + graphOL->setXColumn(colOutlierV); + graphOL->setDrawLine(false); + graphOL->setSymbolSize(graphOL->getSymbolSize()/2.0); + graphOL->setColor(graph->getLineColor()); + return std::pair(graph, graphOL); +} + + + + + + #endif // JKQTPGRAPHSSTATISTICSADAPTORS_H_INCLUDED diff --git a/screenshots/jkqtplotter_simpletest_datastore_groupedstat.png b/screenshots/jkqtplotter_simpletest_datastore_groupedstat.png new file mode 100644 index 0000000000..06555f908e Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_datastore_groupedstat.png differ diff --git a/screenshots/jkqtplotter_simpletest_datastore_groupedstat_barchart.png b/screenshots/jkqtplotter_simpletest_datastore_groupedstat_barchart.png new file mode 100644 index 0000000000..17bf29e80a Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_datastore_groupedstat_barchart.png differ diff --git a/screenshots/jkqtplotter_simpletest_datastore_groupedstat_barchartrawdata.png b/screenshots/jkqtplotter_simpletest_datastore_groupedstat_barchartrawdata.png new file mode 100644 index 0000000000..738c1e5925 Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_datastore_groupedstat_barchartrawdata.png differ diff --git a/screenshots/jkqtplotter_simpletest_datastore_groupedstat_boxplot.png b/screenshots/jkqtplotter_simpletest_datastore_groupedstat_boxplot.png new file mode 100644 index 0000000000..38897633ea Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_datastore_groupedstat_boxplot.png differ diff --git a/screenshots/jkqtplotter_simpletest_datastore_groupedstat_scatter.png b/screenshots/jkqtplotter_simpletest_datastore_groupedstat_scatter.png new file mode 100644 index 0000000000..5d34a9fd96 Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_datastore_groupedstat_scatter.png differ diff --git a/screenshots/jkqtplotter_simpletest_datastore_groupedstat_scatterrawdata.png b/screenshots/jkqtplotter_simpletest_datastore_groupedstat_scatterrawdata.png new file mode 100644 index 0000000000..ef73c4c8c0 Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_datastore_groupedstat_scatterrawdata.png differ diff --git a/screenshots/jkqtplotter_simpletest_datastore_groupedstat_small.png b/screenshots/jkqtplotter_simpletest_datastore_groupedstat_small.png new file mode 100644 index 0000000000..4d47f8c16a Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_datastore_groupedstat_small.png differ